diff --git a/docs/api/assets/external-events-uploadExternalSource.png b/docs/api/assets/external-events-uploadExternalSource.png
new file mode 100644
index 0000000..909cbb3
--- /dev/null
+++ b/docs/api/assets/external-events-uploadExternalSource.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9bb5d9bcd51549911df2398f52b3c6da86379c8c48f19589803a80e329cd736d
+size 165198
diff --git a/docs/api/assets/external-events-uploadExternalSourceEventTypes.png b/docs/api/assets/external-events-uploadExternalSourceEventTypes.png
new file mode 100644
index 0000000..4923e91
--- /dev/null
+++ b/docs/api/assets/external-events-uploadExternalSourceEventTypes.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:53a867f7ee954b92706e79b427e3772798a254b26829f06afee18abce925138f
+size 188012
diff --git a/docs/api/examples/external-events.mdx b/docs/api/examples/external-events.mdx
new file mode 100644
index 0000000..59e3bc9
--- /dev/null
+++ b/docs/api/examples/external-events.mdx
@@ -0,0 +1,297 @@
+import uploadExternalSourceEventTypes from '../assets/external-events-uploadExternalSourceEventTypes.png';
+import uploadExternalSource from '../assets/external-events-uploadExternalSource.png';
+
+# External Events
+
+Refer to [External Events](../../../planning/external-events/introduction) for more information on External Events & Sources.
+
+## API Gateway
+External Events & their respective External Sources utilize routes located on [`aerie-gateway`](https://github.com/NASA-AMMOS/aerie-gateway) to perform data validation and upon success, an upload through Hasura/GQL.
+
+
+### Creating External Source & Event Types
+Users should use the following `aerie-gateway` route to upload their "types" file:
+
+
+When uploading through Aerie's UI, External Source & Event types are packaged together in a single `JSON` file which adheres to the meta-schema defined [here](https://github.com/NASA-AMMOS/aerie-gateway/blob/develop/src/schemas/external-event-validation-schemata.ts). **However**, the Gateway route accepts the content of the two top-level fields (`event_types` and `source_types`) separately as the request body.
+
+Uploading a simple definition of a single External Source Type (`ExampleSource`) and a single External Event Type (`ExampleEvent`) should yield the following response:
+
+**Example Input**
+
+`event_types`
+```json
+{
+ "ExampleEvent": {
+ "type": "object",
+ "properties": {
+ "example": {
+ "type": "string"
+ }
+ },
+ "required": [ "example" ]
+ }
+}
+```
+
+`source_types`
+```json
+{
+ "ExampleSource": {
+ "type": "object",
+ "properties": {
+ "example": {
+ "type": "string"
+ }
+ },
+ "required": [ "example" ]
+ }
+}
+```
+
+**Example Output**
+```json
+{
+ "createExternalEventTypes": {
+ "returning": [
+ {
+ "name": "ExampleEvent"
+ }
+ ]
+ },
+ "createExternalSourceTypes": {
+ "returning": [
+ {
+ "name": "ExampleSource"
+ }
+ ]
+ }
+}
+```
+
+### Creating an External Source
+Users should use the following `aerie-gateway` route to upload their External Sources file:
+
+
+When uploading through Aerie's UI, the External Source & it's contained External Events are packaged together in a single `JSON` file which adheres to the meta-schema defined [here](https://github.com/NASA-AMMOS/aerie-gateway/blob/develop/src/schemas/external-event-validation-schemata.ts). **However**, the Gateway route accepts the content of the two top-level fields (`source` and `events`) separately as the request body.
+
+:::info Note
+
+In order to upload an External Source, the **External Source Type** and **External Event Type** **must** exist. For uploading types, see [above](#creating-external-source--event-types).
+
+:::
+
+Uploading a simple definition of an External Source with a single External Event should yield the following result:
+
+**Example Input**
+
+`source`
+```json
+{
+ "attributes": { "example": "Example attribute" },
+ "derivation_group_name": "ExampleSource Default",
+ "key": "ExampleSource:1",
+ "period": {
+ "end_time": "2024-008T00:00:00Z",
+ "start_time": "2024-001T00:00:00Z"
+ },
+ "source_type_name": "ExampleSource",
+ "valid_at": "2024-001T00:00:00Z"
+}
+```
+
+`events`
+```json
+[
+ {
+ "attributes": { "example": "Example attribute" },
+ "duration": "00:00:01",
+ "event_type_name": "ExampleEvent",
+ "key": "ExampleEvent:1",
+ "start_time": "2024-002T00:00:00Z"
+ }
+]
+```
+
+**Example Output**
+```json
+{
+ "upsertDerivationGroup": {
+ "name": "ExampleSource Default"
+ },
+ "createExternalSource": {
+ "attributes": {
+ "example": "Example attribute"
+ },
+ "derivation_group_name": "ExampleSource Default",
+ "end_time": "2024-01-08T00:00:00+00:00",
+ "key": "ExampleSource:1",
+ "source_type_name": "ExampleSource",
+ "start_time": "2024-01-01T00:00:00+00:00",
+ "valid_at": "2024-01-01T00:00:00+00:00"
+ }
+}
+```
+
+## GQL
+The following operations can be performed directly through GQL/Hasura and do not need to interact with Gateway like the above section.
+
+### Associating a Derivation Group to a Plan
+If a plan and a derivation group exist, they can be associated using the following GraphQL mutation:
+
+```graphql
+mutation CreatePlanDerivationGroup($source: plan_derivation_group_insert_input!) {
+ planExternalSourceLink: insert_plan_derivation_group_one(
+ object: $source,
+ on_conflict: {
+ constraint: plan_derivation_group_pkey
+ }
+ ) {
+ derivation_group_name
+ }
+}
+```
+
+This mutation requires a an argument, `$source`, which includes: 1) the name of the derivation group to link, and 2) the ID of the plan to link it to. See below for an example input:
+
+```json
+{
+ "source": {
+ "derivation_group_name": "ExampleSource Default",
+ "plan_id": 1
+ }
+}
+```
+
+This request will yield the following response:
+
+```json
+{
+ "data": {
+ "planExternalSourceLink": {
+ "derivation_group_name": "ExampleSource Default"
+ }
+ }
+}
+```
+
+### Disassociating a Derivation Group from a Plan
+To disassociate a derivation group from a plan, the following GraphQL mutation can be used:
+
+```graphql
+mutation DeletePlanExternalSource($where: plan_derivation_group_bool_exp!) {
+ planDerivationGroupLink: delete_plan_derivation_group(where: $where) {
+ returning {
+ derivation_group_name
+ }
+ }
+}
+```
+
+This mutations requires an argument which is an expression returning a boolean such as:
+
+```json
+{
+ "where": {
+ "_and": {
+ "derivation_group_name": { "_eq": "ExampleSource Default" },
+ "plan_id": { "_eq": 1}
+ }
+ }
+}
+```
+
+This request will yield the following response:
+
+```json
+{
+ "data": {
+ "planDerivationGroupLink": {
+ "returning": [
+ {
+ "derivation_group_name": "ExampleSource Default"
+ }
+ ]
+ }
+ }
+}
+```
+
+### Get External Events
+```graphql
+query GetExternalEvents {
+ external_event {
+ attributes
+ event_type_name
+ key
+ duration
+ start_time
+ source_key
+ }
+}
+```
+
+### Get External Events from an External Source
+```graphql
+query GetExternalEventsFromExternalSource($sourceKey: String!, $derivationGroupName: String!) {
+ external_event(where: {source_key: {_eq: $sourceKey}, derivation_group_name: {_eq: $derivationGroupName}}) {
+ attributes
+ event_type_name
+ key
+ duration
+ start_time
+ source_key
+ }
+}
+```
+
+### Get External Sources
+```graphql
+query GetExternalSources {
+ external_source {
+ attributes
+ created_at
+ derivation_group_name
+ end_time
+ key
+ owner
+ start_time
+ source_type_name
+ valid_at
+ }
+}
+```
+
+### Get External Sources from a Derivation Group
+```graphql
+query GetExternalSourcesFromDerivationGroup($derivationGroupName: String!) {
+ external_source(where: {derivation_group_name: {_eq: $derivationGroupName}}) {
+ attributes
+ created_at
+ derivation_group_name
+ end_time
+ key
+ owner
+ start_time
+ source_type_name
+ valid_at
+ }
+}
+```
+
+### Get Derivation Groups
+```graphql
+query GetDerivationGroup {
+ derivation_group {
+ name
+ owner
+ source_type_name
+ }
+}
+```
diff --git a/docs/planning/assets/external_source_manager_intro.png b/docs/planning/assets/external_source_manager_intro.png
deleted file mode 100644
index 8cb9cdb..0000000
--- a/docs/planning/assets/external_source_manager_intro.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:c4ba57a4db965b33f777e53c27a184d751ced0969c2f3502f0f823b188b9a081
-size 419048
diff --git a/docs/planning/collaboration/merging-plans.mdx b/docs/planning/collaboration/merging-plans.mdx
index 9d7330e..e143fc6 100644
--- a/docs/planning/collaboration/merging-plans.mdx
+++ b/docs/planning/collaboration/merging-plans.mdx
@@ -136,6 +136,6 @@ import approveMerge from './assets/approve-merge.png';
:::info External Events and Plan Merge
-External Events (specifically, derivation groups) are not included in plan snapshots and merges. This will be addressed in a future release. See [External Events](../../external-events) for more information.
+External Events (specifically, derivation groups) are not included in plan snapshots and merges. This will be addressed in a future release. See [External Events](../../external-events/introduction) for more information.
:::
diff --git a/docs/planning/assets/create_derivation_group.png b/docs/planning/external-events/assets/create_derivation_group.png
similarity index 100%
rename from docs/planning/assets/create_derivation_group.png
rename to docs/planning/external-events/assets/create_derivation_group.png
diff --git a/docs/planning/assets/create_external_event_type.png b/docs/planning/external-events/assets/create_external_event_type.png
similarity index 100%
rename from docs/planning/assets/create_external_event_type.png
rename to docs/planning/external-events/assets/create_external_event_type.png
diff --git a/docs/planning/assets/create_external_source_type.png b/docs/planning/external-events/assets/create_external_source_type.png
similarity index 100%
rename from docs/planning/assets/create_external_source_type.png
rename to docs/planning/external-events/assets/create_external_source_type.png
diff --git a/docs/planning/assets/create_groups_and_types_button.png b/docs/planning/external-events/assets/create_groups_and_types_button.png
similarity index 100%
rename from docs/planning/assets/create_groups_and_types_button.png
rename to docs/planning/external-events/assets/create_groups_and_types_button.png
diff --git a/docs/planning/assets/derivation_example_full.png b/docs/planning/external-events/assets/derivation_example_full.png
similarity index 100%
rename from docs/planning/assets/derivation_example_full.png
rename to docs/planning/external-events/assets/derivation_example_full.png
diff --git a/docs/planning/assets/derivation_group_motivation.png b/docs/planning/external-events/assets/derivation_group_motivation.png
similarity index 100%
rename from docs/planning/assets/derivation_group_motivation.png
rename to docs/planning/external-events/assets/derivation_group_motivation.png
diff --git a/docs/planning/assets/derivation_group_motivation_ii.png b/docs/planning/external-events/assets/derivation_group_motivation_ii.png
similarity index 100%
rename from docs/planning/assets/derivation_group_motivation_ii.png
rename to docs/planning/external-events/assets/derivation_group_motivation_ii.png
diff --git a/docs/planning/assets/derivation_motivation.png b/docs/planning/external-events/assets/derivation_motivation.png
similarity index 100%
rename from docs/planning/assets/derivation_motivation.png
rename to docs/planning/external-events/assets/derivation_motivation.png
diff --git a/docs/planning/assets/external_event_options.png b/docs/planning/external-events/assets/external_event_options.png
similarity index 100%
rename from docs/planning/assets/external_event_options.png
rename to docs/planning/external-events/assets/external_event_options.png
diff --git a/docs/planning/assets/external_event_table.png b/docs/planning/external-events/assets/external_event_table.png
similarity index 100%
rename from docs/planning/assets/external_event_table.png
rename to docs/planning/external-events/assets/external_event_table.png
diff --git a/docs/planning/assets/external_events_before.png b/docs/planning/external-events/assets/external_events_before.png
similarity index 100%
rename from docs/planning/assets/external_events_before.png
rename to docs/planning/external-events/assets/external_events_before.png
diff --git a/docs/planning/assets/external_events_derivation_group_disabled.png b/docs/planning/external-events/assets/external_events_derivation_group_disabled.png
similarity index 100%
rename from docs/planning/assets/external_events_derivation_group_disabled.png
rename to docs/planning/external-events/assets/external_events_derivation_group_disabled.png
diff --git a/docs/planning/assets/external_events_derivation_group_enabled.png b/docs/planning/external-events/assets/external_events_derivation_group_enabled.png
similarity index 100%
rename from docs/planning/assets/external_events_derivation_group_enabled.png
rename to docs/planning/external-events/assets/external_events_derivation_group_enabled.png
diff --git a/docs/planning/assets/external_events_group_by_event_type.png b/docs/planning/external-events/assets/external_events_group_by_event_type.png
similarity index 100%
rename from docs/planning/assets/external_events_group_by_event_type.png
rename to docs/planning/external-events/assets/external_events_group_by_event_type.png
diff --git a/docs/planning/assets/external_events_group_by_source.png b/docs/planning/external-events/assets/external_events_group_by_source.png
similarity index 100%
rename from docs/planning/assets/external_events_group_by_source.png
rename to docs/planning/external-events/assets/external_events_group_by_source.png
diff --git a/docs/planning/assets/external_events_on_timeline.png b/docs/planning/external-events/assets/external_events_on_timeline.png
similarity index 100%
rename from docs/planning/assets/external_events_on_timeline.png
rename to docs/planning/external-events/assets/external_events_on_timeline.png
diff --git a/docs/planning/assets/external_events_options.png b/docs/planning/external-events/assets/external_events_options.png
similarity index 100%
rename from docs/planning/assets/external_events_options.png
rename to docs/planning/external-events/assets/external_events_options.png
diff --git a/docs/planning/assets/external_events_table.png b/docs/planning/external-events/assets/external_events_table.png
similarity index 100%
rename from docs/planning/assets/external_events_table.png
rename to docs/planning/external-events/assets/external_events_table.png
diff --git a/docs/planning/external-events/assets/external_source_manager_intro.png b/docs/planning/external-events/assets/external_source_manager_intro.png
new file mode 100644
index 0000000..1323b7c
--- /dev/null
+++ b/docs/planning/external-events/assets/external_source_manager_intro.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:409f16965dd7a275b1308e6bdc60d6472f8223cad65ee6996adbfcaf67968360
+size 552123
diff --git a/docs/planning/external-events/assets/external_source_manager_types_expanded.png b/docs/planning/external-events/assets/external_source_manager_types_expanded.png
new file mode 100644
index 0000000..0cb4b10
--- /dev/null
+++ b/docs/planning/external-events/assets/external_source_manager_types_expanded.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b6647c3710b3a72223ebb568989dab262693d56c4e34ef49a39279f526f102b1
+size 213950
diff --git a/docs/planning/external-events/assets/external_source_manager_types_page.png b/docs/planning/external-events/assets/external_source_manager_types_page.png
new file mode 100644
index 0000000..d8f4dfe
--- /dev/null
+++ b/docs/planning/external-events/assets/external_source_manager_types_page.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9df7b97e66f3d4f49e62eb41539cdbf4e5e63b24e72cde0e3c0857974fbe90fb
+size 153724
diff --git a/docs/planning/assets/external_source_manager_upload.png b/docs/planning/external-events/assets/external_source_manager_upload.png
similarity index 100%
rename from docs/planning/assets/external_source_manager_upload.png
rename to docs/planning/external-events/assets/external_source_manager_upload.png
diff --git a/docs/planning/assets/external_sources_table.png b/docs/planning/external-events/assets/external_sources_table.png
similarity index 100%
rename from docs/planning/assets/external_sources_table.png
rename to docs/planning/external-events/assets/external_sources_table.png
diff --git a/docs/planning/assets/inspected_source.png b/docs/planning/external-events/assets/inspected_source.png
similarity index 100%
rename from docs/planning/assets/inspected_source.png
rename to docs/planning/external-events/assets/inspected_source.png
diff --git a/docs/planning/assets/manage_derivation_group_modal.png b/docs/planning/external-events/assets/manage_derivation_group_modal.png
similarity index 100%
rename from docs/planning/assets/manage_derivation_group_modal.png
rename to docs/planning/external-events/assets/manage_derivation_group_modal.png
diff --git a/docs/planning/assets/ordering_external_sources.png b/docs/planning/external-events/assets/ordering_external_sources.png
similarity index 100%
rename from docs/planning/assets/ordering_external_sources.png
rename to docs/planning/external-events/assets/ordering_external_sources.png
diff --git a/docs/planning/assets/plan_external_source_full_view.png b/docs/planning/external-events/assets/plan_external_source_full_view.png
similarity index 100%
rename from docs/planning/assets/plan_external_source_full_view.png
rename to docs/planning/external-events/assets/plan_external_source_full_view.png
diff --git a/docs/planning/assets/plan_external_sources_panel.png b/docs/planning/external-events/assets/plan_external_sources_panel.png
similarity index 100%
rename from docs/planning/assets/plan_external_sources_panel.png
rename to docs/planning/external-events/assets/plan_external_sources_panel.png
diff --git a/docs/planning/assets/plan_selected_external_event.png b/docs/planning/external-events/assets/plan_selected_external_event.png
similarity index 100%
rename from docs/planning/assets/plan_selected_external_event.png
rename to docs/planning/external-events/assets/plan_selected_external_event.png
diff --git a/docs/planning/assets/timeline_and_editor_full.png b/docs/planning/external-events/assets/timeline_and_editor_full.png
similarity index 100%
rename from docs/planning/assets/timeline_and_editor_full.png
rename to docs/planning/external-events/assets/timeline_and_editor_full.png
diff --git a/docs/planning/external-events/external-events-attributes.md b/docs/planning/external-events/external-events-attributes.md
new file mode 100644
index 0000000..200b888
--- /dev/null
+++ b/docs/planning/external-events/external-events-attributes.md
@@ -0,0 +1,164 @@
+# External Event and Source Attributes
+
+This page describes the format for files describing External Source Types and External Event Types. These files detail the allowed attributes that each of these components are required and allowed to have (i.e. the attributes defined in a file, and only those, are eligible to be included in a definition).
+
+Both External Source Types and External Event Types can be detailed in the same file, which has the following general outline:
+
+```json
+{
+ "event_types": {
+ "EventTypeName": {
+ ...
+ },
+ "SecondEventTypeName": {
+ ...
+ },
+ ...
+ },
+ "source_types": {
+ "SourceTypeName": {
+ ...
+ },
+ "AdditionalSourceTypeName": {
+ ...
+ },
+ ...
+ }
+}
+```
+
+Any number of source and event types can be provided in a given file. **At present, there is no explicit tying of external event and source types. That is, a given source type doesn't specify what event types are legal to be included yet.**
+
+We will now elaborate on the details of the actual event and source types, to make it clear how to define allowable/required attributes. In any case, a review of [JSON Schema](https://json-schema.org/learn/getting-started-step-by-step) would be instrumental in making sense of the following sections.
+
+## External Types
+
+An external source type definition might look like the following:
+
+```json
+...
+"Weather": {
+ "type": "object",
+ "required": [
+ "location",
+ "version",
+ "changelog"
+ ],
+ "properties": {
+ "location": {
+ "type": "string"
+ },
+ "version": {
+ "type": "number"
+ },
+ "changelog": {
+ "type": "string"
+ }
+ }
+}
+```
+
+This is an example of an object nested within `source_types`, and describes the attributes allowed for a `Weather` source. In this file, following JSON Schema syntax, the attributes of a `Weather` object are described - we desire an object, with 3 required fields: `location` (a string), `version` (a number), and `changelog` (a string). Additional JSON Schema functionality can be added to these properties as well, like a `pattern` specification, which restricts strings for a give field to follow a regex. These objects also bear an implied `additionalProperties: false`, meaning only these properties can be provided; any extras will be rejected.
+
+Event type attribute specifications function similarly:
+
+```json
+"WeatherReport": {
+ "type": "object",
+ "required": ["daily_high", "daily_low", "precipitation_lik"],
+ "properties": {
+ "daily_high": {
+ "type": "object",
+ "properties": {
+ "value": {
+ "type": "number"
+ },
+ "units": {
+ "type": "string"
+ }
+ },
+ "required": ["units", "value"]
+ },
+ "daily_low": {
+ "type": "object",
+ "properties": {
+ "value": {
+ "type": "number"
+ },
+ "units": {
+ "type": "string"
+ }
+ },
+ "required": ["units", "value"]
+ },
+ "precipitation_lik": {
+ "type": "number"
+ }
+ }
+}
+```
+
+For completeness, we can show that a complete file then looks like the following:
+
+```json
+{
+ "event_types": {
+ "WeatherReport": {
+ "type": "object",
+ "required": ["daily_high", "daily_low", "precipitation_lik"],
+ "properties": {
+ "daily_high": {
+ "type": "object",
+ "properties": {
+ "value": {
+ "type": "number"
+ },
+ "units": {
+ "type": "string"
+ }
+ },
+ "required": ["units", "value"]
+ },
+ "daily_low": {
+ "type": "object",
+ "properties": {
+ "value": {
+ "type": "number"
+ },
+ "units": {
+ "type": "string"
+ }
+ },
+ "required": ["units", "value"]
+ },
+ "precipitation_lik": {
+ "type": "number"
+ }
+ }
+ }
+ },
+ "source_types": {
+ "Weather": {
+ "type": "object",
+ "required": [
+ "location",
+ "version",
+ "changelog"
+ ],
+ "properties": {
+ "location": {
+ "type": "string"
+ },
+ "version": {
+ "type": "number"
+ },
+ "changelog": {
+ "type": "string"
+ }
+ }
+ }
+ }
+}
+```
+
+As can be seen, nested objects are very much fair play in these attribute definitions. The primary requirement is an adherence to JSON Schema syntax. Should a planner fail to do so in creating one of these files, they will be met with a rejection from AERIE as well as a specification of where their attribute specification was wrong.
\ No newline at end of file
diff --git a/docs/planning/external-events.mdx b/docs/planning/external-events/introduction.mdx
similarity index 70%
rename from docs/planning/external-events.mdx
rename to docs/planning/external-events/introduction.mdx
index 52b3df9..8250816 100644
--- a/docs/planning/external-events.mdx
+++ b/docs/planning/external-events/introduction.mdx
@@ -8,10 +8,8 @@ import externalEventsWithResourcesAndActivities from './assets/external_events_b
import externalEventLayerOptions from './assets/external_event_options.png';
import externalSourceOrdering from './assets/ordering_external_sources.png';
import externalSourceManager from './assets/external_source_manager_intro.png';
-import externalSourceManagerCreateDerivationGroup from './assets/create_derivation_group.png';
-import externalSourceManagerCreateExternalEventType from './assets/create_external_event_type.png';
-import externalSourceManagerCreateExternalSourceType from './assets/create_external_source_type.png';
-import externalSourceManagerCreateGroupsAndTypesButton from './assets/create_groups_and_types_button.png';
+import externalSourceManagerTypesPage from './assets/external_source_manager_types_page.png';
+import externalSourceManagerTypesExpanded from './assets/external_source_manager_types_expanded.png';
import externalSourceManagerUpload from './assets/external_source_manager_upload.png';
import externalSourceTable from './assets/external_sources_table.png';
import externalSourceInspected from './assets/inspected_source.png';
@@ -45,10 +43,10 @@ External Events represent temporal occurrences outside of the locus of control o
External Sources are containers for External Events and the primary way that users interact with External Events. To get External Events into Aerie, an External Source must be uploaded that contains the event definitions inside. See [External Sources](#external-sources-1) below for more information.
#### External Event Types
-External Event Types define the *typing* of each External Event. This typing groups External Events on the basis of the data they represent. For example, an External Event may be of the type `Ground Station Contact`, `Solar Flare`, or `Weather Forecast`.
+External Event Types define the *typing* of each External Event. This typing groups External Events on the basis of the data they represent, and details the allowed attributes that a given External Event is allowed to have. For example, an External Event may be of the type `Ground Station Contact`, `Solar Flare`, or `Weather Forecast`. Each of these types contains a schema for a set of allowed/defined attributes which are then implemented by the events using this External Event Type to display additional data, such as `station`, `flux level`, or `precipitation`.
#### External Source Types
-External Source Types define the *typing* of each External Source. This typing groups External Sources on the basis of the data they contain. For example, you may have an External Source Type of `Weather Report` to represent all your weather reports, and inside each of the `Weather Report`-typed sources you can expect to find External Events that share a common External Event Type that appears in all `Weather Report`-typed sources (ex: Temperature).
+External Source Types define the *typing* of each External Source. This typing groups External Sources on the basis of the data they contain, and details the allowed attributes that a given External Source can have to describe the data contained within it. For example, you may have an External Source Type of `Weather Report` to represent all your weather reports, and inside each of the `Weather Report`-typed sources you can expect to find External Events that share a common External Event Type that appears in all `Weather Report`-typed sources (ex: Temperature). Identical to [External Event Types](#external-event-types), External Source Types also contain attribute schemas that are then implemented by the External Sources using the External Source Type.
#### Derivation Groups
Derivation Groups are collections of External Sources that can be associated with plans. Within a Derivation Group, the collective External Events from its member External Sources are used to create a *derived* set of events for the Derivation Group. See [Derivation](#derivation) below for more information.
@@ -72,22 +70,11 @@ The need for these became apparent after an exploration of External Events imple
Figure 2: External Events - External Events with resources and activities
-:::info Note
-
-Currently, External Events are *not* accessible to the automated scheduler for purposes of generating activities based on events, satisfying constraints, or other interactions with other data in Aerie. However, this is in the planned scope for External Events, and future releases will add these capabilities
-
-:::
-
### External Sources
**External Sources** represent a collection of External Events. When we upload External Events, we can only do so by uploading them in an External Source.
-These sources are to be defined in `JSON`, following a general format that will be discussed below. Any data a user wishes to turn into an External Source/External Events should be converted to the `JSON` format to allow ingest within Aerie.
-
-:::info Note
+These sources are defined using [JSON Schema](https://json-schema.org/) format with a [meta-schema](https://github.com/NASA-AMMOS/aerie-gateway/blob/develop/src/schemas/external-event-validation-schemata.ts) enforced to ensure certain fields such as `key` and `start_time` are present and in the correct format. Additionally, the
-There is currently no well-defined, official `JSON` schema for External Source input, however there are required fields which will be mentioned below, and any non-known fields included will be ignored during ingest. Additionally, no tool currently exists to provide the generic translation to the `JSON` format, however this is a feature planned for a future release.
-
-:::
#### Schema
There are two parts to each External Source: 1) a `source` header and 2) a collection of `events`:
@@ -104,7 +91,7 @@ There are two parts to each External Source: 1) a `source` header and 2) a colle
##### Source
-The `source` field includes the following fields:
+The `source` field includes the following fields, where **all** are required:
* `key`
* Unique identifier for the External Source
@@ -135,6 +122,21 @@ The `source` field includes the following fields:
...
```
+* `attributes`
+ * An object that includes additional data relevant to the External Source in question.
+ * Must follow the schema as defined by the External Source Type
+ * For a Weather Forecast file, this may include details about the location, which version this file is, and notes about what changed between this version and the last.
+ * ***Example***
+ ```json
+ ...,
+ "attributes": {
+ "location": "Greenbelt, MD",
+ "version": 2,
+ "changelog": "Updated precipitation likelihood for 2024-007T00:00:00 from 20% to 35%."
+ },
+ ...
+ ```
+
##### Events
Events are represented as a set of objects contained in a list, and each event has the following fields:
@@ -142,7 +144,7 @@ Events are represented as a set of objects contained in a list, and each event h
* `key`
* Unique identifier for the External Event
* Uniqueness is required within the External Source, but **not** across different External Sources. For more information, see [derivation](#derivation)
- * Currently has no restrictions or requirements, though those can be optionally imposed by users - see [Formal JSON Schema](#formal-json-schema) for more information
+ * Currently has no restrictions or requirements
* **Example**: `ExampleEvent:1/sc/sc1:1:X/1`
* `event_type`
@@ -158,6 +160,93 @@ Events are represented as a set of objects contained in a list, and each event h
* This value may be 0 to represent an instantaneous event (ex: time of sunrise/sunset)
* **Example**: `00:30:00`
+* `attributes`
+ * Similar to attributes for External Sources, this property lists various characteristics of a given event not directly implied by the above fields' values.
+ * Must follow the schema as defined by the External Event Type
+ * For a Weather Forecast file, a given event may require properties detailing the likelihood of precipitation, or the wind speed.
+ * **Example:**
+ ```json
+ ...,
+ "attributes": {
+ "precipitation_lik": 0.35,
+ "wind_speed (mph)": 3
+ },
+ ...
+ ```
+
+##### Full External Source & Event Types Example
+
+The following is a full example of a valid, `JSON` representation of an External Source Type and External Event Type. The type definitions **must** be uploaded to Aerie *prior* to attempting to use them in an External Source and/or External Event(s)!
+
+The example represents the definitions for a weather forecast source & event.
+
+```json
+{
+ "event_types": {
+ "WeatherReport": {
+ "type": "object",
+ "required": ["daily_high", "daily_low", "precipitation_lik"],
+ "properties": {
+ "daily_high": {
+ "type": "object",
+ "properties": {
+ "value": {
+ "type": "number"
+ },
+ "units": {
+ "type": "string"
+ }
+ },
+ "required": ["units", "value"]
+ },
+ "daily_low": {
+ "type": "object",
+ "properties": {
+ "value": {
+ "type": "number"
+ },
+ "units": {
+ "type": "string"
+ }
+ },
+ "required": ["units", "value"]
+ },
+ "precipitation_lik": {
+ "type": "number"
+ }
+ }
+ }
+ },
+ "source_types": {
+ "Weather": {
+ "type": "object",
+ "required": [
+ "location",
+ "version",
+ "changelog"
+ ],
+ "properties": {
+ "location": {
+ "type": "string"
+ },
+ "version": {
+ "type": "number"
+ },
+ "changelog": {
+ "type": "string"
+ }
+ }
+ }
+ }
+}
+```
+
+:::info Note
+
+For more information on External Source & Type definitions & attribute schemas, see [External Events and Source Attributes](../external-events-attributes)
+
+:::
+
##### Full External Source Example
The following is a full example of a valid, `JSON` representation of an External Source that can be ingested by Aerie.
@@ -167,63 +256,145 @@ The example represents a week-long weather forecast where each event is the repo
```json
{
"source": {
- "key": "WeatherForecast2024001_2024008.json",
- "source_type": "WeatherForecast",
- "valid_at": "2024-01-00T00:00:00Z",
+ "key": "WEATHER_2024001_2024008_IDEAL.V00.json",
+ "source_type": "Weather",
+ "valid_at": "2024-001T00:00:00Z",
"period": {
"start_time": "2024-001T00:00:00Z",
"end_time": "2024-008T00:00:00Z"
+ },
+ "attributes": {
+ "location": "Greenbelt, MD",
+ "version": 2,
+ "changelog": "Updated precipitation_lik for 2024-007T00:00:00 from 20% to 35%."
}
},
"events": [
{
- "key": "Weather/Day/001",
+ "key": "W/Day/001",
"event_type": "WeatherReport",
"start_time": "2024-001T00:00:00Z",
- "duration": "24:00:00"
+ "duration": "24:00:00",
+ "attributes": {
+ "daily_high": {
+ "value": 43.2,
+ "units": "F"
+ },
+ "daily_low": {
+ "value": 32.9,
+ "units": "F"
+ },
+ "precipitation_lik": 0.7
+ }
},
{
- "key": "Weather/Day/002",
+ "key": "W/Day/002",
"event_type": "WeatherReport",
"start_time": "2024-002T00:00:00Z",
- "duration": "24:00:00"
+ "duration": "24:00:00",
+ "attributes": {
+ "daily_high": {
+ "value": 40.5,
+ "units": "F"
+ },
+ "daily_low": {
+ "value": 29.2,
+ "units": "F"
+ },
+ "precipitation_lik": 0.6
+ }
},
{
- "key": "Weather/Day/003",
+ "key": "W/Day/003",
"event_type": "WeatherReport",
"start_time": "2024-003T00:00:00Z",
- "duration": "24:00:00"
+ "duration": "24:00:00",
+ "attributes": {
+ "daily_high": {
+ "value": 42.1,
+ "units": "F"
+ },
+ "daily_low": {
+ "value": 28.4,
+ "units": "F"
+ },
+ "precipitation_lik": 0.5
+ }
},
{
- "key": "Weather/Day/004",
+ "key": "W/Day/004",
"event_type": "WeatherReport",
"start_time": "2024-004T00:00:00Z",
- "duration": "24:00:00"
+ "duration": "24:00:00",
+ "attributes": {
+ "daily_high": {
+ "value": 50.0,
+ "units": "F"
+ },
+ "daily_low": {
+ "value": 32.1,
+ "units": "F"
+ },
+ "precipitation_lik": 0.4
+ }
},
{
- "key": "Weather/Day/005",
+ "key": "W/Day/005",
"event_type": "WeatherReport",
"start_time": "2024-005T00:00:00Z",
- "duration": "24:00:00"
+ "duration": "24:00:00",
+ "attributes": {
+ "daily_high": {
+ "value": 46.3,
+ "units": "F"
+ },
+ "daily_low": {
+ "value": 21.0,
+ "units": "F"
+ },
+ "precipitation_lik": 0.3
+ }
},
{
- "key": "Weather/Day/006",
+ "key": "W/Day/006",
"event_type": "WeatherReport",
"start_time": "2024-006T00:00:00Z",
- "duration": "24:00:00"
+ "duration": "24:00:00",
+ "attributes": {
+ "daily_high": {
+ "value": 34.3,
+ "units": "F"
+ },
+ "daily_low": {
+ "value": 22.5,
+ "units": "F"
+ },
+ "precipitation_lik": 0.2
+ }
},
{
- "key": "Weather/Day/007",
+ "key": "W/Day/007",
"event_type": "WeatherReport",
"start_time": "2024-007T00:00:00Z",
- "duration": "24:00:00"
- },
+ "duration": "24:00:00",
+ "attributes": {
+ "daily_high": {
+ "value": 39.0,
+ "units": "F"
+ },
+ "daily_low": {
+ "value": 35.3,
+ "units": "F"
+ },
+ "precipitation_lik": 0.35
+ }
+ }
]
}
```
:::info Note
-Currently, External Sources only accept a `start_time` and an `end_time`, whereas External Events accept only a `start_time` and a `duration`. This may change in the future (i.e. External Events may accept a start time and an end time as well, for example). This is largely due to simplicity in implementation.
+Currently, External Sources only accept a `start_time` and an `end_time`, whereas External Events accept only a `start_time` and a `duration`. This is largely due to simplicity in implementation.
:::
@@ -386,7 +557,7 @@ External Events show up in the UI in two main places - an External Source Manage
:::info Note
-There is also a [tutorial section](../../tutorials/external-events/introduction) that walks through the content of this section in a step-by-step fashion, albeit with less detail.
+There is also a [tutorial section](../../../tutorials/external-events/introduction) that walks through the content of this section in a step-by-step fashion, albeit with less detail.
:::
@@ -398,56 +569,39 @@ The External Source Manager page handles the uploading & inspection of External
Figure 8: External Source Manager
-#### Creating External Source Types, External Event Types, and Derivation Groups
-Within the External Source Manager, the user is able to create new External Source Types, External Event Types, and Derivation Groups. While this is currently **not required** (and these structures will be automatically created if they don't exist on source upload), it is planned to be the main way of creating these types in the future as each will require a strict schema to generate.
+#### Creating External Source Types and External Event Types
+While derivation groups are automatically created when a user uploads a source file (detailed below), External Source and Event Types require special handling, as they specify allowable attributes as well.
-To create one of these types, click the `Create New Groups or Types` button in the top-right:
+To create these types, navigate to the `Types` tab in the External Source Manager.
-Once the modal has been opened there is a set of tabs - select the tab for the data type you'd like to create:
-
-##### Creating a Derivation Group
-Creating a Derivation Group requires both a name for the group, and a source type to link it with.
-
-
-
-##### Creating an External Source Type
-Creating an External Source Type just requires a name for the type.
+Here, the existing types can be inspected for their contents. Most interestingly, we can discern what attributes are available for a given type. Here, we see the `Weather` source type has 3 attributes: `version` (a number), `location` (a string), and `changelog` (a string).
-##### Creating an External Event Type
-Creating an External Event Type just requires a name for the type.
-
-
+To create any of these sources, a user must upload a [JSON Schema](https://json-schema.org/learn/getting-started-step-by-step) to AERIE. We go in depth on how to write these schemas [here](../external-events-attributes).
#### Uploading an External Source
The main view allows users to upload External Sources. Most of these fields autofill and are immutable once parsed - except the Derivation Group which will be autofilled in the style of `external_source_type Default`, but can be edited by the user before upload.
#### Inspecting an External Source
After uploading an External Source, it will show up in the table on the upper-right pane. This table can be filtered by External Source Type as well as sorted by each of the columns - note the default multi-sorting on the columns `Source Type`, `Derivation Group`, and `Valid At`, which is meant to present the sources in the easiest-to-read manner (grouping by their common types & Derivation Groups, then ordering by their `Valid At` times).
Selecting a source allows for the inspection of the source, which is essentially an in-Aerie rendering of what's included under `source` in the uploaded `JSON` (as discussed earlier). It is here, as well as in the table, that deletion can be performed. Note that for deletion to work, an External Source must not be associated with any existing plan (that is the Derivation Group it is a part of must be dissociated from all plans before deletions become legal). Aside from that, there is currently no system of ownership, meaning admins and users alike, as long as External Sources satisfy the aforementioned condition, can delete at will. Viewers, however, cannot.
@@ -455,23 +609,23 @@ Selecting a source allows for the inspection of the source, which is essentially
It should also be noted that all this inspection takes place outside the context of a plan, so that External Sources & their events can be viewed without having to open and associate the External Source(s) to a plan.
Finally, it is also possible to inspect each source's contained events as a table. This is useful, as Derivation Groups on plan timelines only show what has been derived, meaning anything that has been selected against won't appear. This page is therefore the absolute truth to see everything that is included, derived-out or not, with a given External Source.
### Plan
Once an External Source has been uploaded, it can be viewed and interacted with in the context of a plan.
To begin working with external sources in the plan, the left side panel should be set to the "External Sources" option. This panel is where users (administrators or plan collaborators) can associate different Derivation Groups with the plan.
@@ -481,8 +635,8 @@ To begin working with external sources in the plan, the left side panel should b
There are currently two levels to linking a Derivation Group to a plan: **association** and **enabling**. Association is handled here, via the _Manage Derivation Groups_ button. This presents a modal where users can expand different Derivation Groups to view the associated sources and select whether or not they would like to associate said Derivation Group with their plan.
**Association** simply means that the plan is *aware* of the existence of the Derivation Group, and is the gatekeeper for whether it is visible in the External Sources panel. In this panel lies the second level to linking, which is enabling. **Enabling** simply dictates whether a Derivation Group (even if the filters in the *Timeline Editor* select for it) is *visible* on the timeline. Disabling hides all events associated with the group completely, whereas enabling does the opposite. It does not, however, dissociate the plan and Derivation Group. This is simply a visibility attribute and is actually persisted as part of the view (and even persists after Derivation Group dissociation/reassociation, meaning if a Derivation Group is dissociated and then re-associated, its "enabled" setting stays the same).
@@ -494,16 +648,16 @@ Enabled|Disabled
![Enabled.](./assets/external_events_derivation_group_enabled.png) | ![Disabled.](./assets/external_events_derivation_group_disabled.png)
#### Timeline
The timeline shows any events from Derivation Groups that are associated with the plan, enabled in the current view, and are filtered for in the timeline editor. Having covered the first two, we can now discuss the editor and its effects on the timeline.
The layer of the timeline is modelled after the activity layer, as it provides an easily readable representation of discrete-time occurrences. Layers share the layer options also provided to activity layers, as well as implementing a 'Group By' option specifically for external events. The 'Group By' mechanic allows the user to have external events either grouped by their external source (within the derivation group), or their event types.
@@ -513,16 +667,16 @@ The layer of the timeline is modelled after the activity layer, as it provides a
![External Source](./assets/external_events_group_by_source.png) | ![External Event Type](./assets/external_events_group_by_event_type.png)
#### Tables and Inspection
The screenshot below shows a brief overview of the remaining panels that have been added to plans. It is possible to either mouse over External Events for additional detail or to select them in the timeline, which selects them in a table view beneath the timeline as well as details them in the right pane. This looks as follows:
#### A Note on Views
@@ -532,24 +686,15 @@ As a final note on the frontend, it is worth briefly detailing what parts of the
- _External Event options_ - the options in the timeline editor filter.
## Scheduling Activities from Events
-External events associated with a plan are accessible from the [Procedural Scheduling](../../scheduling-and-constraints/procedural/introduction/) API, just like resources and activities. This allows users to write scheduling goals which create activities based on the presence (or absence) of external events - for example, "create a downlink activity 5 minutes after the start of every 'DSN Contact' type event".
+External events associated with a plan are accessible from the [Procedural Scheduling](../../../scheduling-and-constraints/procedural/introduction/) API, just like resources and activities. This allows users to write scheduling goals which create activities based on the presence (or absence) of external events - for example, "create a downlink activity 5 minutes after the start of every 'DSN Contact' type event".
-To access events in a procedural goal, you must create an External Events timeline object - see [Timelines: External Events](../../scheduling-and-constraints/procedural/timelines/basics/external-events/). A full example of a scheduling goal using events can be found on the [Procedural Scheduling Examples](../../scheduling-and-constraints/procedural/scheduling/examples/#scheduling-based-off-of-external-events) page.
+To access events in a procedural goal, you must create an External Events timeline object - see [Timelines: External Events](../../../scheduling-and-constraints/procedural/timelines/basics/external-events/). A full example of a scheduling goal using events can be found on the [Procedural Scheduling Examples](../../../scheduling-and-constraints/procedural/scheduling/examples/#scheduling-based-off-of-external-events) page.
Currently, external events are **not accessible from the [Declarative Scheduling EDSL](http://localhost:3000/aerie-docs/scheduling-and-constraints/declarative/scheduling/introduction/)** - but we may implement support for this in the future.
## What Remains
Here, we discuss briefly everything that is not currently implemented but that we do plan to in the future.
-### Formal JSON Schema
-We currently lack a formal schema uploaded External Sources and their contained External Events. The extent of our schema is just that we ask users to include the fields described in [External Sources](#external-sources), and that any additionally defined fields will be ignored.
-
-Prior to starting work in the UI, some work on a schema was done. However, it was ultimately ruled that making something restrictive like a schema might be smarter after having done some work on External Events, as it is entirely possible to spend a lot of time on a schema beforehand only to discard or rework a fair amount of it as we progress with development. At this point, we are a lot more confident in what fields should definitely be present in a [JSON Schema](https://json-schema.org/learn/getting-started-step-by-step), which means that creating a definition should be a lot more feasible in a future batch of work.
-
-These Schemae would likely be a part of the mission model themselves; seeing as defining what activities and resources are allowable for a mission plan are part of a mission model, so too would be definitions of allowable External Source Types and External Event Types.
-
-This raises the question of how External Source Types and External Event Types should be handled in a Schema. The idea we are currently floating is a multilayered Schema - one that is common to all sources (and events), which essentially details the fields listed in [External Sources](#external-sources), as those show in any External Source regardless of type. The second layer would constrain for an External Source's `metadata` field (to be included in a future update) and for an External Event's `metadata` field (to be included in a future update). Different External Source Types and External Event Types should have different allowable `metadata`, and as such defining a subschema for these fields becomes necessary to restrict and add uniformity to what should be included in that field given the type. It is these subschemae that we suggest should be part of a mission model. Exactly how this definition is to be created, how these layers are to be reconciled, and how to integrate them with the concept of a mission model is yet to be decided.
-
### Ownership/Roles
Our current solution to a lack of clear ownership/roles around External Sources is as follows:
diff --git a/docs/tutorials/external-events/assets/external_events_tutorial_upload_step3.png b/docs/tutorials/external-events/assets/external_events_tutorial_upload_step3.png
index ffa0f8d..1053c66 100644
--- a/docs/tutorials/external-events/assets/external_events_tutorial_upload_step3.png
+++ b/docs/tutorials/external-events/assets/external_events_tutorial_upload_step3.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:115672a75c4777bf76692decd10bfc7b7dd2b166df26109cf48931fd4eb345dc
-size 331700
+oid sha256:b221faaa2050fb3a9e9a4f51dcf30543aa90d4bdc17cd60c4d9713042153b256
+size 387941
diff --git a/docs/tutorials/external-events/assets/external_events_tutorial_upload_step4.png b/docs/tutorials/external-events/assets/external_events_tutorial_upload_step4.png
index 87a878d..bf9bab2 100644
--- a/docs/tutorials/external-events/assets/external_events_tutorial_upload_step4.png
+++ b/docs/tutorials/external-events/assets/external_events_tutorial_upload_step4.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:8d9496806831fd734e2392a8e28e6e2c9a31fc3a7c88904ec91992cc7179b9a5
-size 348269
+oid sha256:84202eb63dbe87e25d50498b3e1efb0fbb49973ceb53f0e55547560a5d52fa1b
+size 370174
diff --git a/docs/tutorials/external-events/assets/external_source_manager.png b/docs/tutorials/external-events/assets/external_source_manager.png
new file mode 100644
index 0000000..5c8d6ba
--- /dev/null
+++ b/docs/tutorials/external-events/assets/external_source_manager.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3d59232132a31cb486322be8115755ba589ef948dc315e9a815a93966a2866b5
+size 212378
diff --git a/docs/tutorials/external-events/assets/external_type_manager.png b/docs/tutorials/external-events/assets/external_type_manager.png
new file mode 100644
index 0000000..9d2debf
--- /dev/null
+++ b/docs/tutorials/external-events/assets/external_type_manager.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9b75573d2e40ffed01e17ab71ea8eef25699e4b3dd1fe055572305a9b8e09b42
+size 266574
diff --git a/docs/tutorials/external-events/assets/external_type_manager_file_parsed.png b/docs/tutorials/external-events/assets/external_type_manager_file_parsed.png
new file mode 100644
index 0000000..968c197
--- /dev/null
+++ b/docs/tutorials/external-events/assets/external_type_manager_file_parsed.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f0196fa1c1300924f05c7a87fc8d7637beb12b708a5a6a39ad87f9f6dc7a82be
+size 79520
diff --git a/docs/tutorials/external-events/assets/external_type_manager_successful_upload.png b/docs/tutorials/external-events/assets/external_type_manager_successful_upload.png
new file mode 100644
index 0000000..5bcf429
--- /dev/null
+++ b/docs/tutorials/external-events/assets/external_type_manager_successful_upload.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2e9805064d586aa1099ee91b60f81efc7d0fe6c19b853d7d8038a58d1e944910
+size 300032
diff --git a/docs/tutorials/external-events/assets/scheduling_goal_modal.png b/docs/tutorials/external-events/assets/scheduling_goal_modal.png
new file mode 100644
index 0000000..9ea85c4
--- /dev/null
+++ b/docs/tutorials/external-events/assets/scheduling_goal_modal.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:505b4650358075c644204480f1a588b065173f18e11edb5fdf6b0629f154250f
+size 197355
diff --git a/docs/tutorials/external-events/assets/scheduling_goal_result.png b/docs/tutorials/external-events/assets/scheduling_goal_result.png
new file mode 100644
index 0000000..62dc858
--- /dev/null
+++ b/docs/tutorials/external-events/assets/scheduling_goal_result.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e42bd6d892b4dd4f180dedf1fd775ca7d289f2a1ca8de34717d7784c63cfc90a
+size 62938
diff --git a/docs/tutorials/external-events/assets/scheduling_goal_upload.png b/docs/tutorials/external-events/assets/scheduling_goal_upload.png
new file mode 100644
index 0000000..a7529b0
--- /dev/null
+++ b/docs/tutorials/external-events/assets/scheduling_goal_upload.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c01d7e7da06cb7cf9eefb485cbe7a3a9b1faf8276a83f64612080695e9a8f215
+size 281773
diff --git a/docs/tutorials/external-events/associating-derivation-groups.mdx b/docs/tutorials/external-events/associating-derivation-groups.mdx
index 5a70c2d..0b4f52c 100644
--- a/docs/tutorials/external-events/associating-derivation-groups.mdx
+++ b/docs/tutorials/external-events/associating-derivation-groups.mdx
@@ -13,7 +13,13 @@ import externalEventsTutorialTimelineEditor from './assets/external_events_tutor
import externalEventsTutorialFilterShown from './assets/external_events_tutorial_filter_shown.png';
# Associating the Derivation Group with a Plan
-Now that we have some External Sources uploaded, we can utilize them within a plan to see them on a timeline (and in the future, use them to power constraints, dictate scheduling goals, etc.).
+Now that we have some External Sources uploaded, we can utilize them within a plan to see them on a timeline!
+
+:::caution Note
+
+Prior to creating a plan, a mission model must exist - currently, the mission model is not tied directly to any external event/source features, so any mission model can be used with any external sources/events.
+
+:::
## Creating a Plan
Start by going to the Aerie **Plan** page:
@@ -26,18 +32,21 @@ Once there, create a new plan with the following parameters:
-To create this plan, make sure that there exists _some_ mission model that can be associated with the plan. The exact model is, at present, entirely unimportant as it has no bearing on External Events functionality. The mission model used here, arbitrarily, is that of Aerie's mission model template.
+:::info Note
+
+ The `start` and `end` times are important here, as they are the bounds that contain all the external events in the source we uploaded!
+
+:::
-After the plan has been created, select the plan on the table to the right, and then select **Open plan** in the pane on the left. You should be presented with a plan view that resembles the image below:
+After the plan has been created, select the plan on the table to the right, and then select `Open plan` in the pane on the left. You should be presented with a plan view that resembles the image below:
-Select the `External Sources` tab on the left, and you should see the following:
+Click the drop-down menu in the top-right (currently on `Activity, Resource, External Event Types`) and select the `External Sources` tab. You should see the following:
-Click the 'x' next to 'Selected External Source' to deselect it, then repeat these steps with the second file. The table should now look as follows:
+Click the `X` next to `Selected External Source` to deselect it, then repeat these steps with the second file. The table should now look as follows:
diff --git a/docs/upgrade-guides/2-21-0-to-3-0-0.md b/docs/upgrade-guides/2-21-0-to-3-0-0.md
index a1db2b5..dfd40b0 100644
--- a/docs/upgrade-guides/2-21-0-to-3-0-0.md
+++ b/docs/upgrade-guides/2-21-0-to-3-0-0.md
@@ -2,5 +2,5 @@
No special instructions are necessary to upgrade to `v3.0.0`.
-Aerie `v3.0.0` includes a new feature to support uploading and visualizing External Events, see the [External Events](https://nasa-ammos.github.io/aerie-docs/planning/external-events/) docs page for more information.
+Aerie `v3.0.0` includes a new feature to support uploading and visualizing External Events, see the [External Events](https://nasa-ammos.github.io/aerie-docs/planning/external-events/introduction) docs page for more information.
diff --git a/sidebars.js b/sidebars.js
index 3492de2..46b0216 100644
--- a/sidebars.js
+++ b/sidebars.js
@@ -31,6 +31,7 @@ const sidebars = {
'api/examples/activity-presets',
'api/examples/advanced-extensions',
'api/examples/tags',
+ 'api/examples/external-events',
],
},
],
@@ -82,6 +83,7 @@ const sidebars = {
'tutorials/external-events/creating-an-external-source',
'tutorials/external-events/uploading-an-external-source',
'tutorials/external-events/associating-derivation-groups',
+ 'tutorials/external-events/creating-a-scheduling-goal-with-external-events',
],
},
],
@@ -155,7 +157,15 @@ const sidebars = {
'planning/create-plan-and-simulate',
'planning/external-datasets',
'planning/activity-directive-metadata',
- 'planning/external-events',
+ {
+ type: 'category',
+ label: 'External Events',
+ link: {
+ id: 'planning/external-events/introduction',
+ type: 'doc',
+ },
+ items: ['planning/external-events/external-events-attributes'],
+ },
{
type: 'category',
label: 'Collaboration',
@@ -189,7 +199,7 @@ const sidebars = {
label: 'Scheduling & Constraints',
link: {
id: 'scheduling-and-constraints/introduction',
- type: 'doc'
+ type: 'doc',
},
items: [
'scheduling-and-constraints/management',
@@ -198,7 +208,7 @@ const sidebars = {
label: 'Procedural',
link: {
id: 'scheduling-and-constraints/procedural/introduction',
- type: 'doc'
+ type: 'doc',
},
items: [
'scheduling-and-constraints/procedural/getting-started',
@@ -207,15 +217,15 @@ const sidebars = {
label: 'Timelines',
link: {
id: 'scheduling-and-constraints/procedural/timelines/introduction',
- type: 'doc'
+ type: 'doc',
},
items: [
{
type: 'category',
- label: "Basics",
+ label: 'Basics',
link: {
id: 'scheduling-and-constraints/procedural/timelines/basics/introduction',
- type: 'doc'
+ type: 'doc',
},
items: [
'scheduling-and-constraints/procedural/timelines/basics/profiles',
@@ -223,23 +233,23 @@ const sidebars = {
'scheduling-and-constraints/procedural/timelines/basics/activities',
'scheduling-and-constraints/procedural/timelines/basics/external-events',
'scheduling-and-constraints/procedural/timelines/basics/windows',
- 'scheduling-and-constraints/procedural/timelines/basics/common-operations'
- ]
+ 'scheduling-and-constraints/procedural/timelines/basics/common-operations',
+ ],
},
{
type: 'category',
- label: "Advanced",
+ label: 'Advanced',
link: {
id: 'scheduling-and-constraints/procedural/timelines/advanced/introduction',
- type: 'doc'
+ type: 'doc',
},
items: [
// 'scheduling-and-constraints/procedural/timelines/advanced/parallel-profiles',
// 'scheduling-and-constraints/procedural/timelines/advanced/custom-operations',
// 'scheduling-and-constraints/procedural/timelines/advanced/custom-timelines'
- ]
- }
- ]
+ ],
+ },
+ ],
},
'scheduling-and-constraints/procedural/plan-and-sim-results',
'scheduling-and-constraints/procedural/constraints',
@@ -248,22 +258,20 @@ const sidebars = {
label: 'Scheduling',
link: {
id: 'scheduling-and-constraints/procedural/scheduling/introduction',
- type: 'doc'
+ type: 'doc',
},
- items: [
- 'scheduling-and-constraints/procedural/scheduling/examples'
- ]
+ items: ['scheduling-and-constraints/procedural/scheduling/examples'],
},
'scheduling-and-constraints/procedural/parameters-and-invocations',
// 'scheduling-and-constraints/procedural/running-externally'
- ]
+ ],
},
{
type: 'category',
label: 'Declarative',
link: {
id: 'scheduling-and-constraints/declarative/introduction',
- type: 'doc'
+ type: 'doc',
},
items: [
{
@@ -302,10 +310,10 @@ const sidebars = {
},
],
},
- ]
+ ],
},
- 'scheduling-and-constraints/execution'
- ]
+ 'scheduling-and-constraints/execution',
+ ],
},
{
type: 'category',