From 338830e925bf1170c1f0663c6b7e407daac1484a Mon Sep 17 00:00:00 2001 From: Eric Windmill Date: Mon, 4 Apr 2022 14:52:53 -0400 Subject: [PATCH 1/2] adds snippets for ODM --- packages/firebase_snippets_app/.gitignore | 1 - .../lib/snippets/firestore_odm.dart | 27 ++ .../snippets/firestore_odm/address_model.dart | 17 + .../snippets/firestore_odm/user_model.dart | 38 +++ .../lib/widgets/user.dart | 36 +++ .../lib/widgets/users_list.dart | 33 ++ packages/firebase_snippets_app/pubspec.lock | 300 +++++++++++++++++- packages/firebase_snippets_app/pubspec.yaml | 5 + 8 files changed, 453 insertions(+), 4 deletions(-) create mode 100644 packages/firebase_snippets_app/lib/snippets/firestore_odm.dart create mode 100644 packages/firebase_snippets_app/lib/snippets/firestore_odm/address_model.dart create mode 100644 packages/firebase_snippets_app/lib/snippets/firestore_odm/user_model.dart create mode 100644 packages/firebase_snippets_app/lib/widgets/user.dart create mode 100644 packages/firebase_snippets_app/lib/widgets/users_list.dart diff --git a/packages/firebase_snippets_app/.gitignore b/packages/firebase_snippets_app/.gitignore index a0454fe..0fa6b67 100644 --- a/packages/firebase_snippets_app/.gitignore +++ b/packages/firebase_snippets_app/.gitignore @@ -30,7 +30,6 @@ .pub-cache/ .pub/ /build/ -*.g.dart # Web related lib/generated_plugin_registrant.dart diff --git a/packages/firebase_snippets_app/lib/snippets/firestore_odm.dart b/packages/firebase_snippets_app/lib/snippets/firestore_odm.dart new file mode 100644 index 0000000..ffa66d0 --- /dev/null +++ b/packages/firebase_snippets_app/lib/snippets/firestore_odm.dart @@ -0,0 +1,27 @@ +// ignore_for_file: non_constant_identifier_names + +import 'package:firebase_snippets_app/snippets/firestore_odm/user_model.dart'; +import 'package:firebase_snippets_app/snippets/snippet_base.dart'; + +class ODMSnippets extends DocSnippet { + @override + void runAll() { + // TODO: implement runAll + } + + void references_performQueries() async { + // [START references_perform_queries] + usersRef.whereName(isEqualTo: 'John'); + usersRef.whereAge(isGreaterThan: 18); + usersRef.orderByAge(); + // ..etc! + // [END references_perform_queries] + } + + void subCollection_accessSubCollection() async { + // [START sub_collection_access_sub_collection] + AddressCollectionReference addressesRef = + usersRef.doc('myDocumentID').addresses; + // [END sub_collection_access_sub_collection] + } +} diff --git a/packages/firebase_snippets_app/lib/snippets/firestore_odm/address_model.dart b/packages/firebase_snippets_app/lib/snippets/firestore_odm/address_model.dart new file mode 100644 index 0000000..1c92548 --- /dev/null +++ b/packages/firebase_snippets_app/lib/snippets/firestore_odm/address_model.dart @@ -0,0 +1,17 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'address_model.g.dart'; + +// [START sub_collections_define] +@JsonSerializable() +class Address { + final String streetName; + + Address({required this.streetName}); + + factory Address.fromJson(Map json) => + _$AddressFromJson(json); + + Map toJson() => _$AddressToJson(this); +} +// [END sub_collections_define] diff --git a/packages/firebase_snippets_app/lib/snippets/firestore_odm/user_model.dart b/packages/firebase_snippets_app/lib/snippets/firestore_odm/user_model.dart new file mode 100644 index 0000000..5b5a0a2 --- /dev/null +++ b/packages/firebase_snippets_app/lib/snippets/firestore_odm/user_model.dart @@ -0,0 +1,38 @@ +// ignore_for_file: non_constant_identifier_names + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:cloud_firestore_odm/cloud_firestore_odm.dart'; +import 'package:firebase_snippets_app/snippets/firestore_odm/address_model.dart'; +import 'package:json_annotation/json_annotation.dart'; + +part 'user_model.g.dart'; + +@JsonSerializable() +class User { + User({ + required this.name, + required this.age, + required this.email, + required this.address, + }) { + _$assertUser(this); + } + + factory User.fromJson(Map json) => _$UserFromJson(json); + + final String name; + final String email; + final Address address; + + @Min(0) + final int age; + + Map toJson() => _$UserToJson(this); +} +// [END defining_models] + +// [START references_collection_ref] +@Collection('users') +@Collection
('users/*/addresses') +final usersRef = UserCollectionReference(); +// [END references_collection_ref] diff --git a/packages/firebase_snippets_app/lib/widgets/user.dart b/packages/firebase_snippets_app/lib/widgets/user.dart new file mode 100644 index 0000000..4f00169 --- /dev/null +++ b/packages/firebase_snippets_app/lib/widgets/user.dart @@ -0,0 +1,36 @@ +// ignore_for_file: use_key_in_widget_constructors + +import 'package:cloud_firestore_odm/cloud_firestore_odm.dart'; +import 'package:flutter/material.dart'; + +import '../snippets/firestore_odm/user_model.dart'; + +// Not currently in the docs, so not currently being tested. +class UserLabel extends StatelessWidget { + const UserLabel(this.id); + + final String id; + + @override + Widget build(BuildContext context) { + return FirestoreBuilder( + // Access a specific document + ref: usersRef.doc(id), + builder: (context, AsyncSnapshot snapshot, + Widget? child) { + if (snapshot.hasError) return const Text('Something went wrong!'); + if (!snapshot.hasData) return const Text('Loading user...'); + + // Access the UserDocumentSnapshot + UserDocumentSnapshot documentSnapshot = snapshot.requireData; + + if (!documentSnapshot.exists) { + return const Text('User does not exist.'); + } + + User user = documentSnapshot.data!; + + return Text('User name: ${user.name}, age ${user.age}'); + }); + } +} diff --git a/packages/firebase_snippets_app/lib/widgets/users_list.dart b/packages/firebase_snippets_app/lib/widgets/users_list.dart new file mode 100644 index 0000000..e449391 --- /dev/null +++ b/packages/firebase_snippets_app/lib/widgets/users_list.dart @@ -0,0 +1,33 @@ +import 'package:cloud_firestore_odm/cloud_firestore_odm.dart'; +import 'package:flutter/material.dart'; + +import '../snippets/firestore_odm/user_model.dart'; + +// Not currently in the docs, so not currently being tested. +class UsersList extends StatelessWidget { + const UsersList({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return FirestoreBuilder( + ref: usersRef, + builder: (context, AsyncSnapshot snapshot, + Widget? child) { + if (snapshot.hasError) return const Text('Something went wrong!'); + if (!snapshot.hasData) return const Text('Loading users...'); + + // Access the QuerySnapshot + UserQuerySnapshot querySnapshot = snapshot.requireData; + + return ListView.builder( + itemCount: querySnapshot.docs.length, + itemBuilder: (context, index) { + // Access the User instance + User user = querySnapshot.docs[index].data; + + return Text('User name: ${user.name}, age ${user.age}'); + }, + ); + }); + } +} diff --git a/packages/firebase_snippets_app/pubspec.lock b/packages/firebase_snippets_app/pubspec.lock index b0fb3b3..0d245b8 100644 --- a/packages/firebase_snippets_app/pubspec.lock +++ b/packages/firebase_snippets_app/pubspec.lock @@ -1,6 +1,20 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + url: "https://pub.dartlang.org" + source: hosted + version: "31.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.dartlang.org" + source: hosted + version: "2.8.0" archive: dependency: transitive description: @@ -8,6 +22,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.1.6" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.0" async: dependency: transitive description: @@ -22,6 +43,62 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + build: + dependency: transitive + description: + name: build + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.1" + build_config: + dependency: transitive + description: + name: build_config + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + build_daemon: + dependency: transitive + description: + name: build_daemon + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.6" + build_runner: + dependency: "direct dev" + description: + name: build_runner + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.8" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + url: "https://pub.dartlang.org" + source: hosted + version: "7.2.3" + built_collection: + dependency: transitive + description: + name: built_collection + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + url: "https://pub.dartlang.org" + source: hosted + version: "8.1.4" characters: dependency: transitive description: @@ -36,6 +113,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.1" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + cli_util: + dependency: transitive + description: + name: cli_util + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.5" clock: dependency: transitive description: @@ -49,21 +140,35 @@ packages: name: cloud_firestore url: "https://pub.dartlang.org" source: hosted - version: "3.1.8" + version: "3.1.11" + cloud_firestore_odm: + dependency: "direct main" + description: + name: cloud_firestore_odm + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0-dev.11" + cloud_firestore_odm_generator: + dependency: "direct dev" + description: + name: cloud_firestore_odm_generator + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0-dev.11" cloud_firestore_platform_interface: dependency: transitive description: name: cloud_firestore_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "5.4.13" + version: "5.5.2" cloud_firestore_web: dependency: transitive description: name: cloud_firestore_web url: "https://pub.dartlang.org" source: hosted - version: "2.6.8" + version: "2.6.11" cloud_functions: dependency: "direct main" description: @@ -85,6 +190,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.2.9" + code_builder: + dependency: transitive + description: + name: code_builder + url: "https://pub.dartlang.org" + source: hosted + version: "4.1.0" collection: dependency: transitive description: @@ -92,6 +204,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.15.0" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" crypto: dependency: transitive description: @@ -99,6 +218,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.0.1" + dart_style: + dependency: transitive + description: + name: dart_style + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.1" fake_async: dependency: transitive description: @@ -204,6 +330,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.2.10" + fixnum: + dependency: transitive + description: + name: fixnum + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" flutter: dependency: "direct main" description: flutter @@ -231,11 +364,32 @@ packages: description: flutter source: sdk version: "0.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" fuchsia_remote_debug_protocol: dependency: transitive description: flutter source: sdk version: "0.0.0" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + graphs: + dependency: transitive + description: + name: graphs + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" http: dependency: transitive description: @@ -243,6 +397,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.13.4" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + url: "https://pub.dartlang.org" + source: hosted + version: "3.2.0" http_parser: dependency: transitive description: @@ -255,6 +416,13 @@ packages: description: flutter source: sdk version: "0.0.0" + io: + dependency: transitive + description: + name: io + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" js: dependency: transitive description: @@ -262,6 +430,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.6.3" + json_annotation: + dependency: "direct main" + description: + name: json_annotation + url: "https://pub.dartlang.org" + source: hosted + version: "4.4.0" + json_serializable: + dependency: "direct dev" + description: + name: json_serializable + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.5" lints: dependency: transitive description: @@ -269,6 +451,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.1" + logging: + dependency: transitive + description: + name: logging + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" matcher: dependency: transitive description: @@ -290,6 +479,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.7.0" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + package_config: + dependency: transitive + description: + name: package_config + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" path: dependency: transitive description: @@ -360,6 +563,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.2" + pool: + dependency: transitive + description: + name: pool + url: "https://pub.dartlang.org" + source: hosted + version: "1.5.0" process: dependency: transitive description: @@ -367,11 +577,60 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.2.4" + pub_semver: + dependency: transitive + description: + name: pub_semver + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + recase: + dependency: transitive + description: + name: recase + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" + shelf: + dependency: transitive + description: + name: shelf + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.1" + source_helper: + dependency: transitive + description: + name: source_helper + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" source_span: dependency: transitive description: @@ -393,6 +652,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + stream_transform: + dependency: transitive + description: + name: stream_transform + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" string_scanner: dependency: transitive description: @@ -421,6 +687,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.4.8" + timing: + dependency: transitive + description: + name: timing + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" typed_data: dependency: transitive description: @@ -442,6 +715,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "7.5.0" + watcher: + dependency: transitive + description: + name: watcher + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" webdriver: dependency: transitive description: @@ -463,6 +750,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.2.0+1" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" sdks: dart: ">=2.16.1 <3.0.0" flutter: ">=2.8.0" diff --git a/packages/firebase_snippets_app/pubspec.yaml b/packages/firebase_snippets_app/pubspec.yaml index 65a7adf..182eb00 100644 --- a/packages/firebase_snippets_app/pubspec.yaml +++ b/packages/firebase_snippets_app/pubspec.yaml @@ -30,6 +30,8 @@ dependencies: firebase_storage: ^10.2.9 firebase_messaging: ^11.2.11 path_provider: ^2.0.9 + cloud_firestore_odm: ^1.0.0-dev.11 + json_annotation: ^4.4.0 dev_dependencies: flutter_test: @@ -37,6 +39,9 @@ dev_dependencies: integration_test: sdk: flutter flutter_lints: ^1.0.0 + build_runner: ^2.1.8 + cloud_firestore_odm_generator: ^1.0.0-dev.11 + json_serializable: ^6.1.5 flutter: uses-material-design: true From 7e58de2cb2627fc4309e5541f5060227dd3e4944 Mon Sep 17 00:00:00 2001 From: Eric Windmill Date: Mon, 11 Apr 2022 10:43:13 -0400 Subject: [PATCH 2/2] fix pubspec --- packages/firebase_snippets_app/pubspec.lock | 103 ++++++++++---------- 1 file changed, 53 insertions(+), 50 deletions(-) diff --git a/packages/firebase_snippets_app/pubspec.lock b/packages/firebase_snippets_app/pubspec.lock index 0245c23..554a4a9 100644 --- a/packages/firebase_snippets_app/pubspec.lock +++ b/packages/firebase_snippets_app/pubspec.lock @@ -175,21 +175,21 @@ packages: name: cloud_functions url: "https://pub.dartlang.org" source: hosted - version: "3.2.10" + version: "3.2.11" cloud_functions_platform_interface: dependency: transitive description: name: cloud_functions_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "5.1.1" + version: "5.1.2" cloud_functions_web: dependency: transitive description: name: cloud_functions_web url: "https://pub.dartlang.org" source: hosted - version: "4.2.9" + version: "4.2.10" code_builder: dependency: transitive description: @@ -252,7 +252,7 @@ packages: name: firebase_auth url: "https://pub.dartlang.org" source: hosted - version: "3.3.12" + version: "3.3.13" firebase_auth_platform_interface: dependency: transitive description: @@ -266,14 +266,14 @@ packages: name: firebase_auth_web url: "https://pub.dartlang.org" source: hosted - version: "3.3.10" + version: "3.3.11" firebase_core: dependency: "direct main" description: name: firebase_core url: "https://pub.dartlang.org" source: hosted - version: "1.12.0" + version: "1.14.0" firebase_core_platform_interface: dependency: transitive description: @@ -308,21 +308,21 @@ packages: name: firebase_messaging url: "https://pub.dartlang.org" source: hosted - version: "11.2.11" + version: "11.2.12" firebase_messaging_platform_interface: dependency: transitive description: name: firebase_messaging_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "3.2.1" + version: "3.2.2" firebase_messaging_web: dependency: transitive description: name: firebase_messaging_web url: "https://pub.dartlang.org" source: hosted - version: "2.2.9" + version: "2.2.10" firebase_ml_model_downloader: dependency: "direct main" description: @@ -343,42 +343,42 @@ packages: name: firebase_remote_config url: "https://pub.dartlang.org" source: hosted - version: "2.0.2" + version: "2.0.3" firebase_remote_config_platform_interface: dependency: transitive description: name: firebase_remote_config_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "1.1.1" + version: "1.1.2" firebase_remote_config_web: dependency: transitive description: name: firebase_remote_config_web url: "https://pub.dartlang.org" source: hosted - version: "1.0.7" + version: "1.0.8" firebase_storage: dependency: "direct main" description: name: firebase_storage url: "https://pub.dartlang.org" source: hosted - version: "10.2.9" + version: "10.2.11" firebase_storage_platform_interface: dependency: transitive description: name: firebase_storage_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "4.1.1" + version: "4.1.2" firebase_storage_web: dependency: transitive description: name: firebase_storage_web url: "https://pub.dartlang.org" source: hosted - version: "3.2.10" + version: "3.2.11" fixnum: dependency: transitive description: @@ -402,21 +402,21 @@ packages: name: flutter_facebook_auth url: "https://pub.dartlang.org" source: hosted - version: "4.1.2" + version: "4.2.0" flutter_facebook_auth_platform_interface: dependency: transitive description: name: flutter_facebook_auth_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "3.0.1" + version: "3.1.0" flutter_facebook_auth_web: dependency: transitive description: name: flutter_facebook_auth_web url: "https://pub.dartlang.org" source: hosted - version: "3.0.0+1" + version: "3.1.0" flutter_lints: dependency: "direct dev" description: @@ -434,39 +434,25 @@ packages: description: flutter source: sdk version: "0.0.0" - frontend_server_client: + flutter_webview_plugin: dependency: transitive description: - name: frontend_server_client + name: flutter_webview_plugin url: "https://pub.dartlang.org" source: hosted - version: "2.1.2" - flutter_webview_plugin: + version: "0.3.11" + frontend_server_client: dependency: transitive description: - name: flutter_webview_plugin + name: frontend_server_client url: "https://pub.dartlang.org" source: hosted - version: "0.3.11" + version: "2.1.2" fuchsia_remote_debug_protocol: dependency: transitive description: flutter source: sdk version: "0.0.0" - glob: - dependency: transitive - description: - name: glob - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.2" - graphs: - dependency: transitive - description: - name: graphs - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" github_sign_in: dependency: "direct main" description: @@ -474,6 +460,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.0.4" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" google_sign_in: dependency: "direct main" description: @@ -495,6 +488,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.10.0+5" + graphs: + dependency: transitive + description: + name: graphs + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" http: dependency: transitive description: @@ -521,20 +521,20 @@ packages: description: flutter source: sdk version: "0.0.0" - io: + intl: dependency: transitive description: - name: io + name: intl url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" - intl: + version: "0.17.0" + io: dependency: transitive description: - name: intl + name: io url: "https://pub.dartlang.org" source: hosted - version: "0.17.0" + version: "1.0.3" js: dependency: transitive description: @@ -703,6 +703,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" + quiver: + dependency: transitive + description: + name: quiver + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1+1" recase: dependency: transitive description: @@ -721,13 +728,9 @@ packages: dependency: transitive description: name: shelf_web_socket - quiver: - dependency: transitive - description: - name: quiver url: "https://pub.dartlang.org" source: hosted - version: "3.0.1+1" + version: "1.0.1" sign_in_with_apple: dependency: "direct main" description: @@ -886,7 +889,7 @@ packages: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "2.4.4" + version: "2.5.1" xdg_directories: dependency: transitive description: