• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

MerginMaps / input / 6418704545

05 Oct 2023 12:00PM UTC coverage: 61.936% (+0.04%) from 61.9%
6418704545

Pull #2835

github

tomasMizera
bring back button to account page to get to the dashboard
Pull Request #2835: Remove subscription pages for iOS and call-to-actions

7589 of 12253 relevant lines covered (61.94%)

102.28 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

37.31
/app/inputhelp.cpp
1
/***************************************************************************
2
 *                                                                         *
3
 *   This program is free software; you can redistribute it and/or modify  *
4
 *   it under the terms of the GNU General Public License as published by  *
5
 *   the Free Software Foundation; either version 2 of the License, or     *
6
 *   (at your option) any later version.                                   *
7
 *                                                                         *
8
 ***************************************************************************/
9

10
#include "inputhelp.h"
11
#include "merginuserauth.h"
12
#include "merginuserinfo.h"
13
#include "merginsubscriptioninfo.h"
14
#include "merginsubscriptionstatus.h"
15
#include "merginapi.h"
16
#include "inpututils.h"
17
#include "coreutils.h"
18

19
#include "inpututils.h"
20

21
#include <QNetworkReply>
22
#include <QSysInfo>
23

24
const QString helpRoot = QStringLiteral( "https://merginmaps.com/docs" );
25
const QString reportLogUrl = QStringLiteral( "https://g4pfq226j0.execute-api.eu-west-1.amazonaws.com/mergin_client_log_submit" );
26
const QString helpDeskMail = QStringLiteral( "support@merginmaps.com" );
27
const QString inputWeb = QStringLiteral( "https://merginmaps.com" );
28

29
const QString utmTagHelp = QStringLiteral( "?utm_source=input-help&utm_medium=help&utm_campaign=input" );
30
const QString utmTagSubscription = QStringLiteral( "?utm_source=input-subs&utm_medium=subs&utm_campaign=input" );
31
const QString utmTagOther = QStringLiteral( "?utm_source=input-other&utm_medium=other&utm_campaign=input" );
32
const QString utmTagAttention = QStringLiteral( "?utm_source=input-app&utm_medium=attention-required" );
33

34

35
InputHelp::InputHelp( MerginApi *merginApi, InputUtils *utils ):
18✔
36
  mMerginApi( merginApi ),
18✔
37
  mInputUtils( utils )
18✔
38
{
39
  connect( mMerginApi, &MerginApi::apiRootChanged, this, &InputHelp::merginLinkChanged );
18✔
40

41
  emit linkChanged();
18✔
42
}
18✔
43

44
QString InputHelp::helpRootLink() const
1✔
45
{
46
  return helpRoot + "/" + utmTagHelp;
2✔
47
}
48

49
QString InputHelp::inputWebLink() const
1✔
50
{
51
  return inputWeb + "/" +  utmTagOther;
2✔
52
}
53

54
QString InputHelp::merginWebLink() const
1✔
55
{
56
  if ( mMerginApi && mMerginApi->apiRoot() != MerginApi::defaultApiRoot() )
1✔
57
  {
58
    return mMerginApi->apiRoot(); // UTM tags are included only for production server
×
59
  }
60

61
  return MerginApi::defaultApiRoot() + utmTagOther;
2✔
62
}
63

64
QString InputHelp::merginDashboardLink() const
1✔
65
{
66
  QString activeWorkspacePathPart;
1✔
67

68
  if ( mMerginApi && mMerginApi->apiSupportsWorkspaces() )
1✔
69
  {
70
    int activeWS = mMerginApi->userInfo()->activeWorkspaceId();
1✔
71
    if ( activeWS >= 0 )
1✔
72
    {
73
      activeWorkspacePathPart = QStringLiteral( "?workspace=%1&" ).arg( activeWS );
×
74
    }
75
  }
76

77
  if ( mMerginApi && mMerginApi->apiRoot() != MerginApi::defaultApiRoot() )
1✔
78
  {
79
    return mMerginApi->apiRoot() + "dashboard" + activeWorkspacePathPart;
×
80
  }
81

82
  // Let's include UTM tags for production server
83
  QString queryParams;
1✔
84

85
  if ( !activeWorkspacePathPart.isEmpty() )
1✔
86
  {
87
    queryParams = activeWorkspacePathPart;
×
88

89
    // URL can not have two question marks, let's remove the one in the utm tag
90
    QString utms( utmTagAttention );
×
91
    utms.replace( "?", "" );
×
92
    queryParams += utms;
×
93
  }
×
94
  else
95
  {
96
    queryParams = utmTagAttention;
1✔
97
  }
98

99
  return MerginApi::defaultApiRoot() + "dashboard" + queryParams;
2✔
100
}
1✔
101

102
QString InputHelp::privacyPolicyLink() const
1✔
103
{
104
  return helpRoot + "/misc/privacy/" + utmTagOther;
2✔
105
}
106

107
QString InputHelp::merginSubscriptionDetailsLink() const
1✔
108
{
109
  return helpRoot + "/setup/subscriptions/" + utmTagSubscription;
2✔
110
}
111

112
QString InputHelp::howToEnableDigitizingLink() const
1✔
113
{
114
  return helpRoot + "/gis/enable_digitising/" + utmTagHelp;
2✔
115
}
116

117
QString InputHelp::howToEnableBrowsingDataLink() const
1✔
118
{
119
  return helpRoot + "/gis/enable_browsing/" + utmTagHelp;
2✔
120
}
121

122
QString InputHelp::howToSetupThemesLink() const
1✔
123
{
124
  return helpRoot + "/gis/setup_themes/" + utmTagHelp;
2✔
125
}
126

127
QString InputHelp::howToCreateNewProjectLink() const
1✔
128
{
129
  return helpRoot + "/manage/create-project/" + utmTagHelp;
2✔
130
}
131

132
QString InputHelp::howToDownloadProjectLink() const
1✔
133
{
134
  return helpRoot + "/manage/data_sync/" + utmTagHelp;
2✔
135
}
136

137
QString InputHelp::howToSetupProj() const
1✔
138
{
139
  return helpRoot + "/gis/proj/" + utmTagHelp;
2✔
140
}
141

142
QString InputHelp::gpsAccuracyHelpLink() const
1✔
143
{
144
  return helpRoot + "/field/gps_accuracy/" + utmTagHelp;
2✔
145
}
146

147
QString InputHelp::howToConnectGPSLink() const
1✔
148
{
149
  return helpRoot + "/field/external_gps/" + utmTagHelp;
2✔
150
}
151

152
QString InputHelp::merginTermsLink() const
1✔
153
{
154
  return MerginApi::marketingPageRoot() + "terms-of-service" + utmTagOther;
2✔
155
}
156

157
QString InputHelp::projectLoadingErrorHelpLink() const
1✔
158
{
159
  return helpRoot + "/field/broken-project/" + utmTagHelp;
2✔
160
}
161

162
QString InputHelp::whatsNewPostLink() const
1✔
163
{
164
  return inputWeb + "/blog/introducing-workspaces-simplified-collaboration" + utmTagOther;
2✔
165
}
166

167
bool InputHelp::submitReportPending() const
×
168
{
169
  return mSubmitReportPending;
×
170
}
171

172
QString InputHelp::fullLog( bool isHtml )
×
173
{
174
  qint64 limit = 500000;
×
175
  QVector<QString> retLines = logHeader( isHtml );
×
176

177
  QFile file( CoreUtils::logFilename() );
×
178
  if ( file.open( QIODevice::ReadOnly ) )
×
179
  {
180
    qint64 fileSize = file.size();
×
181
    if ( fileSize > limit )
×
182
      file.seek( file.size() - limit );
×
183

184
    QString line = file.readLine();
×
185
    while ( !line.isNull() )
×
186
    {
187
      retLines.push_back( line );
×
188
      line = file.readLine();
×
189
    }
190

191
    file.close();
×
192
  }
×
193
  else
194
  {
195
    retLines.push_back( QString( "Unable to open log file %1" ).arg( CoreUtils::logFilename() ) );
×
196
  }
197

198
  QString ret;
×
199
  int i = 0;
×
200
  for ( const QString &str : retLines )
×
201
  {
202
    ++i;
×
203
    if ( isHtml )
×
204
      ret += QStringLiteral( "<p class=\"%1\">" ).arg( i % 2 == 0 ? "odd" : "even" ) + str.trimmed() + "</p>";
×
205
    else
206
      ret += str.trimmed() + "\n";
×
207
  }
208

209
  return ret;
×
210
}
×
211

212
QVector<QString> InputHelp::logHeader( bool isHtml )
×
213
{
214
  QVector<QString> retLines;
×
215
  retLines.push_back( QStringLiteral( "Input App: %1 - %2 (%3)" ).arg( CoreUtils::appVersion() ).arg( InputUtils::appPlatform() ).arg( CoreUtils::appVersionCode() ) );
×
216
  retLines.push_back( QStringLiteral( "System: %1" ).arg( QSysInfo::prettyProductName() ) );
×
217
  retLines.push_back( QStringLiteral( "Mergin URL: %1" ).arg( mMerginApi->apiRoot() ) );
×
218
  retLines.push_back( QStringLiteral( "Mergin User: %1" ).arg( mMerginApi->userAuth()->username() ) );
×
219
  if ( !mMerginApi->userInfo()->email().isEmpty() )
×
220
  {
221
    retLines.push_back( QStringLiteral( "Mergin Data: %1/%2 Bytes" )
×
222
                        .arg( InputUtils::bytesToHumanSize( mMerginApi->workspaceInfo()->diskUsage() ) )
×
223
                        .arg( InputUtils::bytesToHumanSize( mMerginApi->workspaceInfo()->storageLimit() ) ) );
×
224
    retLines.push_back( QStringLiteral( "Subscription plan: %1" ).arg( mMerginApi->subscriptionInfo()->planAlias() ) );
×
225
    retLines.push_back( QStringLiteral( "Subscription Status: %1" ).arg( MerginSubscriptionStatus::toString( static_cast<MerginSubscriptionStatus::SubscriptionStatus>( mMerginApi->subscriptionInfo()->subscriptionStatus() ) ) ) );
×
226
  }
227
  else
228
  {
229
    retLines.push_back( QStringLiteral( "%1Mergin User Profile not available. To include it, open you Profile Page in InputApp%2" ).arg( isHtml ? "<b>" : "" ).arg( isHtml ? "</b>" : "" ) );
×
230
  }
231
  retLines.push_back( QStringLiteral( "------------------------------------------" ) );
×
232
  retLines.push_back( QStringLiteral( "Screen Info:" ) );
×
233
  retLines.append( InputUtils().dumpScreenInfo().split( "\n" ).toVector() );
×
234
  retLines.push_back( QStringLiteral( "------------------------------------------" ) );
×
235
  retLines.push_back( QStringLiteral( "Profiler Data:" ) );
×
236
  retLines.append( InputUtils().qgisProfilerLog() );
×
237
  retLines.push_back( QStringLiteral( "------------------------------------------" ) );
×
238

239
  return retLines;
×
240
}
×
241

242

243
void InputHelp::submitReport()
×
244
{
245
  // There is a limit of 1MB on the remote service, send less, let say half of that
246
  QString log = fullLog( false );
×
247
  QByteArray logArr = log.toUtf8();
×
248
  QString app = QStringLiteral( "input-%1-%2" ).arg( InputUtils::appPlatform() ).arg( CoreUtils::appVersion() );
×
249
  QString username = mMerginApi->userAuth()->username().toHtmlEscaped();
×
250
  if ( username.isEmpty() )
×
251
    username = "unknown";
×
252
  QString params = QStringLiteral( "?app=%1&username=%2" ).arg( app ).arg( username );
×
253
  QNetworkRequest req( reportLogUrl + params );
×
254
  req.setRawHeader( "User-Agent", "InputApp" );
×
255
  req.setRawHeader( "Content-Type", "text/plain" );
×
256
  QNetworkReply *reply = mManager.post( req, logArr );
×
257
  qDebug() << "Report to " << reportLogUrl;
×
258

259
  mSubmitReportPending = true;
×
260
  emit submitReportPendingChanged();
×
261
  connect( reply, &QNetworkReply::finished, this, &InputHelp::onSubmitReportReplyFinished );
×
262
}
×
263

264
void InputHelp::onSubmitReportReplyFinished()
×
265
{
266
  mSubmitReportPending = false;
×
267
  emit submitReportPendingChanged();
×
268

269
  QNetworkReply *r = qobject_cast<QNetworkReply *>( sender() );
×
270
  Q_ASSERT( r );
×
271

272
  if ( r->error() == QNetworkReply::NoError )
×
273
  {
274
    CoreUtils::log( "submit report", "Report submitted!" );
×
275
    emit mInputUtils->showNotification( tr( "Report submitted.%1Please contact us on%1%2" ).arg( "<br />" ).arg( helpDeskMail ) );
×
276
  }
277
  else
278
  {
279
    CoreUtils::log( "submit report", QStringLiteral( "FAILED - %1" ).arg( r->errorString() ) );
×
280
    emit mInputUtils->showNotification( tr( "Failed to submit report.%1Please check your internet connection." ).arg( "<br>" ) );
×
281
  }
282
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc