Skip to content

Commit

Permalink
Feedback google forms iframe (#26864)
Browse files Browse the repository at this point in the history
* google forms

* iframe

* Fix tests

---------

Co-authored-by: darkhan.nausharipov <darkhan.nausharipov@kzn.akvelon.com>
  • Loading branch information
alexeyinkin and darkhan.nausharipov committed Jun 1, 2023
1 parent e1b4ed3 commit 538c7bd
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 68 deletions.
2 changes: 0 additions & 2 deletions learning/tour-of-beam/frontend/lib/locator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ import 'router/page_factory.dart';
import 'router/route_information_parser.dart';
import 'state.dart';

final _client = CloudFunctionsTobClient();

Future<void> initializeServiceLocator() async {
await _initializeRepositories();
_initializeAuth();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,16 @@ import '../common/examples.dart';

Future<void> checkFeedback(WidgetTester wt) async {
for (final rating in FeedbackRating.values) {
for (final send in [true, false]) {
await _checkFeedback(
wt,
rating: rating,
send: send,
);
}
await _checkFeedback(
wt,
rating: rating,
);
}
}

Future<void> _checkFeedback(
WidgetTester wt, {
required FeedbackRating rating,
required bool send,
}) async {
await wt.tapAndSettle(find.feedbackThumb(rating));

Expand All @@ -47,29 +43,11 @@ Future<void> _checkFeedback(
rating: rating,
snippetContext: defaultEventSnippetContext,
),
reason: 'Rating: $rating, Send: $send',
reason: 'Rating: $rating, Send: false',
);
expect(find.feedbackDropdownContent(), findsOneWidget);

if (!send) {
await wt.tapAndSettle(find.dismissibleOverlay());
} else {
final text = 'This is $rating text.';
await wt.enterText(find.feedbackDropdownTextField(), text);
await wt.pumpAndSettle();

expect(find.text(text), findsOneWidget);

await wt.tapAndSettle(find.feedbackDropdownSendButton());

expectLastAnalyticsEvent(
FeedbackFormSentAnalyticsEvent(
rating: rating,
text: text,
snippetContext: defaultEventSnippetContext,
),
);
}
await wt.tapAndSettle(find.dismissibleOverlay());

expect(find.feedbackDropdownContent(), findsNothing);
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,8 @@ class BeamLinks {
static const playgroundGitHub =
'https://github.com/apache/beam/tree/master/playground';
static const scioGitHub = 'https://github.com/spotify/scio';

// Forms
static const feedbackGoogleForms =
'https://docs.google.com/forms/d/e/1FAIpQLSd5_5XeOwwW2yjEVHUXmiBad8Lxk-4OtNcgG45pbyAZzd4EbA/viewform?usp=pp_url';
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import 'package:flutter_svg/flutter_svg.dart';

import '../../playground_components.dart';
import '../assets/assets.gen.dart';
import 'iframe/iframe.dart';

class FeedbackWidget extends StatelessWidget {
static const positiveRatingButtonKey = Key('positive');
Expand Down Expand Up @@ -156,19 +157,6 @@ class FeedbackDropdown extends StatelessWidget {
required this.subtitle,
});

void _sendFeedback() {
PlaygroundComponents.analyticsService.sendUnawaited(
FeedbackFormSentAnalyticsEvent(
rating: rating,
text: controller.textController.text,
snippetContext: controller.eventSnippetContext,
additionalParams: controller.additionalParams,
),
);
controller.textController.clear();
close();
}

@override
Widget build(BuildContext context) {
return AnimatedBuilder(
Expand All @@ -178,42 +166,26 @@ class FeedbackDropdown extends StatelessWidget {
borderRadius: BorderRadius.circular(8),
),
padding: const EdgeInsets.all(16),
width: 400,
width: 500,
height: MediaQuery.of(context).size.height - 100,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
title,
style: Theme.of(context).textTheme.headlineLarge,
),
const SizedBox(height: BeamSizes.size8),
const SizedBox(height: BeamSizes.size6),
Text(
subtitle,
textAlign: TextAlign.center,
),
const SizedBox(height: BeamSizes.size8),
TextField(
key: textFieldKey,
controller: controller.textController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
const SizedBox(height: BeamSizes.size16),
const Expanded(
child: IFrameWidget(
url: BeamLinks.feedbackGoogleForms,
viewType: 'feedbackGoogleForms',
),
keyboardType: TextInputType.multiline,
maxLines: 5,
minLines: 3,
),
const SizedBox(height: BeamSizes.size8),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
ElevatedButton(
key: sendButtonKey,
onPressed: controller.textController.text.isEmpty
? null
: _sendFeedback,
child: const Text('widgets.feedback.send').tr(),
),
],
),
],
),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

export 'iframe_non_web.dart' if (dart.library.html) 'iframe_web.dart';
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// ignore: avoid_web_libraries_in_flutter

import 'package:flutter/widgets.dart';

class IFrameWidget extends StatefulWidget {
final String url;
final String viewType;

const IFrameWidget({
required this.url,
required this.viewType,
});

@override
State<IFrameWidget> createState() => _IFrameWidgetState();
}

class _IFrameWidgetState extends State<IFrameWidget> {
@override
Widget build(BuildContext context) {
return ErrorWidget('This only works in web.');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// ignore: avoid_web_libraries_in_flutter
import 'dart:html' as html;
import 'dart:ui' as ui;

import 'package:flutter/material.dart';

class IFrameWidget extends StatefulWidget {
final String url;
final String viewType;

const IFrameWidget({
required this.url,
required this.viewType,
});

@override
State<IFrameWidget> createState() => _IFrameWidgetState();
}

class _IFrameWidgetState extends State<IFrameWidget> {
final _iFrameElement = html.IFrameElement();

@override
void initState() {
// ignore: unsafe_html
_iFrameElement.src = widget.url;
_iFrameElement.style.border = 'none';
// ignore: undefined_prefixed_name, avoid_dynamic_calls
ui.platformViewRegistry.registerViewFactory(
widget.viewType,
(int viewId) => _iFrameElement,
);

super.initState();
}

@override
Widget build(BuildContext context) {
return HtmlElementView(
viewType: widget.viewType,
);
}
}

0 comments on commit 538c7bd

Please sign in to comment.