feature[TW19113]: ICD - Integrate rest API - interface submessages
- Adds angular code utilizing the following apis:
platform type api, logical type api, message api, sub message api, structure api, element api
- Polishes up some unit tests
Change-Id: I83f05014c742f30e710ba73379d3b3d06a6b70c1
diff --git a/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/InterfaceElementSearchEndpoint.java b/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/InterfaceElementSearchEndpoint.java
new file mode 100644
index 0000000..370b5ee9
--- /dev/null
+++ b/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/InterfaceElementSearchEndpoint.java
@@ -0,0 +1,72 @@
+/*********************************************************************
+ * Copyright (c) 2021 Boeing
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Boeing - initial API and implementation
+ **********************************************************************/
+package org.eclipse.osee.mim;
+
+import java.util.Collection;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import org.eclipse.osee.framework.core.data.ArtifactId;
+import org.eclipse.osee.mim.types.ElementPosition;
+import org.eclipse.osee.mim.types.InterfaceStructureElementToken;
+
+/**
+ * @author Luciano T. Vaglienti
+ */
+@Path("elements")
+public interface InterfaceElementSearchEndpoint {
+
+ @GET()
+ @Path("filter")
+ @Produces(MediaType.APPLICATION_JSON)
+ /**
+ * Same as /types/ GET() returns a *blank* filtered request
+ *
+ * @return list of elements
+ */
+ Collection<InterfaceStructureElementToken> getElements();
+
+ @GET()
+ @Path("filter/{filter}")
+ @Produces(MediaType.APPLICATION_JSON)
+ /**
+ * Gets List of filtered Platform Types
+ *
+ * @return List of elements
+ */
+ Collection<InterfaceStructureElementToken> getElements(@PathParam("filter") String filter);
+
+ /**
+ * Gets list of elements utilizing platform type
+ *
+ * @param platformTypeId platform type to look for
+ * @return list of elements
+ */
+ @GET()
+ @Path("getType/{typeId}")
+ @Produces(MediaType.APPLICATION_JSON)
+ Collection<InterfaceStructureElementToken> getElementsOfType(@PathParam("typeId") ArtifactId platformTypeId);
+
+ /**
+ * Finds the structure, submessages, and message an element belongs to, for navigation purposes todo.
+ *
+ * @param elementId element to find the structure for
+ * @return relationship structure that contains the element
+ */
+ @GET()
+ @Path("{id}/find")
+ @Produces(MediaType.APPLICATION_JSON)
+ ElementPosition findElement(@PathParam("id") ArtifactId elementId);
+}
diff --git a/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/InterfaceStructureSearchEndpoint.java b/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/InterfaceStructureSearchEndpoint.java
new file mode 100644
index 0000000..cdc18c4
--- /dev/null
+++ b/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/InterfaceStructureSearchEndpoint.java
@@ -0,0 +1,38 @@
+/*********************************************************************
+ * Copyright (c) 2021 Boeing
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Boeing - initial API and implementation
+ **********************************************************************/
+package org.eclipse.osee.mim;
+
+import java.util.Collection;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import org.eclipse.osee.mim.types.InterfaceStructureToken;
+
+/**
+ * @author Luciano T. Vaglienti
+ */
+@Path("structures")
+public interface InterfaceStructureSearchEndpoint {
+
+ @GET()
+ @Path("filter")
+ @Produces(MediaType.APPLICATION_JSON)
+ Collection<InterfaceStructureToken> getAllStructures();
+
+ @GET()
+ @Path("filter/{filter}")
+ @Produces(MediaType.APPLICATION_JSON)
+ Collection<InterfaceStructureToken> getFilteredStructures(@PathParam("filter") String filter);
+}
diff --git a/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/internal/ArtifactInserterImpl.java b/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/internal/ArtifactInserterImpl.java
index 90878c5..66c73d5 100644
--- a/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/internal/ArtifactInserterImpl.java
+++ b/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/internal/ArtifactInserterImpl.java
@@ -27,6 +27,7 @@
import org.eclipse.osee.framework.core.data.UserId;
import org.eclipse.osee.framework.core.enums.SystemUser;
import org.eclipse.osee.framework.jdk.core.result.XResultData;
+import org.eclipse.osee.framework.jdk.core.type.NamedIdBase;
import org.eclipse.osee.framework.jdk.core.util.Lib;
import org.eclipse.osee.mim.ArtifactAccessor;
import org.eclipse.osee.mim.ArtifactInserter;
@@ -234,7 +235,7 @@
user = SystemUser.OseeSystem;
}
TransactionBuilder tx =
- orcsApi.getTransactionFactory().createTransaction(branch, user, "Relate " + this.getObjectTypeToInsert());
+ orcsApi.getTransactionFactory().createTransaction(branch, user, "Unrelate " + this.getObjectTypeToInsert());
tx.unrelate(artifactToUnRelateFrom, relation, artifactToUnRelate);
tx.commit();
} catch (Exception ex) {
@@ -354,13 +355,23 @@
}
private boolean checkIfIdExists(T newArtifact) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
- Long Id = (Long) getGetter(newArtifact.getClass(), "Id").invoke(newArtifact);
- if (Id.equals(null) || Id <= 0L) {
+ Long Id = (Long) getGetter(getNamedIdBase(newArtifact.getClass()), "Id").invoke(newArtifact);
+ if (Id == null || Id <= 0L) {
return false;
}
return true;
}
+ Class<?> getNamedIdBase(Class<?> type) {
+ if (type.getSuperclass() != null) {
+ if (type.getSuperclass() == NamedIdBase.class) {
+ return type.getSuperclass();
+ }
+ return getNamedIdBase(type.getSuperclass());
+ }
+ return null;
+ }
+
List<Field> getAllFields(List<Field> fields, Class<?> type) {
fields.addAll(Arrays.asList(type.getDeclaredFields()));
diff --git a/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/internal/BranchAccessor.java b/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/internal/BranchAccessor.java
index c259fd2..139446d 100644
--- a/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/internal/BranchAccessor.java
+++ b/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/internal/BranchAccessor.java
@@ -23,10 +23,12 @@
import org.eclipse.osee.framework.core.data.BranchId;
import org.eclipse.osee.framework.core.data.UserId;
import org.eclipse.osee.mim.InterfaceElementEndpoint;
+import org.eclipse.osee.mim.InterfaceElementSearchEndpoint;
import org.eclipse.osee.mim.InterfaceMessageEndpoint;
import org.eclipse.osee.mim.InterfaceMessageFilterEndpoint;
import org.eclipse.osee.mim.InterfaceStructureEndpoint;
import org.eclipse.osee.mim.InterfaceStructureFilterEndpoint;
+import org.eclipse.osee.mim.InterfaceStructureSearchEndpoint;
import org.eclipse.osee.mim.InterfaceSubMessageEndpoint;
import org.eclipse.osee.mim.MimApi;
import org.eclipse.osee.mim.PlatformTypesEndpoint;
@@ -97,4 +99,18 @@
return new InterfaceElementEndpointImpl(branch, accountId, messageId, subMessageId, structureId,
mimApi.getInterfaceElementApi(), mimApi.getInterfaceElementArrayApi(), mimApi.getInterfacePlatformTypeApi());
}
+
+ @Path("{branch}/elements")
+ @Produces(MediaType.APPLICATION_JSON)
+ public InterfaceElementSearchEndpoint getElementSearchEndpoint(@PathParam("branch") BranchId branch, @HeaderParam(OSEE_ACCOUNT_ID) UserId accountId) {
+ return new InterfaceElementSearchEndpointImpl(branch, accountId, mimApi.getInterfaceElementApi(),
+ mimApi.getInterfaceElementArrayApi(), mimApi.getInterfacePlatformTypeApi());
+ }
+
+ @Path("{branch}/structures")
+ @Produces(MediaType.APPLICATION_JSON)
+ public InterfaceStructureSearchEndpoint getStructureSearchEndpoint(@PathParam("branch") BranchId branch, @HeaderParam(OSEE_ACCOUNT_ID) UserId accountId) {
+ return new InterfaceStructureSearchEndpointImpl(branch, accountId, mimApi.getInterfaceStructureApi(),
+ mimApi.getInterfaceElementApi(), mimApi.getInterfaceElementArrayApi(), mimApi.getInterfacePlatformTypeApi());
+ }
}
diff --git a/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/internal/InterfaceElementEndpointImpl.java b/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/internal/InterfaceElementEndpointImpl.java
index 3dcd3ea..9104430 100644
--- a/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/internal/InterfaceElementEndpointImpl.java
+++ b/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/internal/InterfaceElementEndpointImpl.java
@@ -20,6 +20,7 @@
import org.eclipse.osee.framework.core.data.UserId;
import org.eclipse.osee.framework.core.enums.CoreRelationTypes;
import org.eclipse.osee.framework.jdk.core.result.XResultData;
+import org.eclipse.osee.framework.jdk.core.util.Lib;
import org.eclipse.osee.mim.InterfaceElementApi;
import org.eclipse.osee.mim.InterfaceElementArrayApi;
import org.eclipse.osee.mim.InterfaceElementEndpoint;
@@ -147,8 +148,23 @@
@Override
public XResultData relatePlatformType(ArtifactId elementId, ArtifactId platformTypeId) {
- return elementApi.getInserter().relateArtifact(platformTypeId, elementId,
- CoreRelationTypes.InterfaceElementPlatformType_PlatformType, branch, account);
+ XResultData results = new XResultData();
+ try {
+ Collection<PlatformTypeToken> platformTypes = platformApi.getAccessor().getAllByRelation(branch,
+ CoreRelationTypes.InterfaceElementPlatformType_Element, elementId, PlatformTypeToken.class);
+ if (platformTypes.size() > 0) {
+ for (PlatformTypeToken token : platformTypes) {
+ results.merge(elementApi.getInserter().unrelateArtifact(ArtifactId.valueOf(token.getId()), elementId,
+ CoreRelationTypes.InterfaceElementPlatformType_PlatformType, branch, account));
+ }
+ }
+ } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
+ | NoSuchMethodException | SecurityException ex) {
+ results.error(Lib.exceptionToString(ex));
+ }
+ results.merge(elementApi.getInserter().relateArtifact(platformTypeId, elementId,
+ CoreRelationTypes.InterfaceElementPlatformType_PlatformType, branch, account));
+ return results;
}
}
diff --git a/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/internal/InterfaceElementSearchEndpointImpl.java b/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/internal/InterfaceElementSearchEndpointImpl.java
new file mode 100644
index 0000000..4de6077
--- /dev/null
+++ b/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/internal/InterfaceElementSearchEndpointImpl.java
@@ -0,0 +1,109 @@
+/*********************************************************************
+ * Copyright (c) 2021 Boeing
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Boeing - initial API and implementation
+ **********************************************************************/
+package org.eclipse.osee.mim.internal;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import org.eclipse.osee.framework.core.data.ArtifactId;
+import org.eclipse.osee.framework.core.data.BranchId;
+import org.eclipse.osee.framework.core.data.UserId;
+import org.eclipse.osee.framework.core.enums.CoreRelationTypes;
+import org.eclipse.osee.mim.InterfaceElementApi;
+import org.eclipse.osee.mim.InterfaceElementArrayApi;
+import org.eclipse.osee.mim.InterfaceElementSearchEndpoint;
+import org.eclipse.osee.mim.InterfacePlatformTypeApi;
+import org.eclipse.osee.mim.types.ElementPosition;
+import org.eclipse.osee.mim.types.InterfaceStructureElementToken;
+import org.eclipse.osee.mim.types.PlatformTypeToken;
+
+/**
+ * @author Luciano T. Vaglienti
+ */
+public class InterfaceElementSearchEndpointImpl implements InterfaceElementSearchEndpoint {
+
+ private final BranchId branch;
+ private final UserId account;
+ private final InterfaceElementApi elementApi;
+ private final InterfaceElementArrayApi elementArrayApi;
+ private final InterfacePlatformTypeApi platformApi;
+
+ public InterfaceElementSearchEndpointImpl(BranchId branch, UserId account, InterfaceElementApi interfaceElementApi, InterfaceElementArrayApi interfaceElementArrayApi, InterfacePlatformTypeApi interfacePlatformTypeApi) {
+ this.account = account;
+ this.branch = branch;
+ this.elementApi = interfaceElementApi;
+ this.elementArrayApi = interfaceElementArrayApi;
+ this.platformApi = interfacePlatformTypeApi;
+ }
+
+ @Override
+ public Collection<InterfaceStructureElementToken> getElements() {
+ try {
+ List<InterfaceStructureElementToken> elements =
+ (List<InterfaceStructureElementToken>) elementApi.getAccessor().getAll(branch,
+ InterfaceStructureElementToken.class);
+ for (InterfaceStructureElementToken element : elements) {
+ PlatformTypeToken platformType = platformApi.getAccessor().getByRelationWithoutId(branch,
+ CoreRelationTypes.InterfaceElementPlatformType_Element, ArtifactId.valueOf(element.getId()),
+ PlatformTypeToken.class);
+ element.setPlatformTypeId(platformType.getId());
+ element.setPlatformTypeName(platformType.getName());
+ }
+ return elements;
+ } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
+ | NoSuchMethodException | SecurityException ex) {
+ return new LinkedList<InterfaceStructureElementToken>();
+ }
+ }
+
+ @Override
+ public Collection<InterfaceStructureElementToken> getElements(String filter) {
+ try {
+ List<InterfaceStructureElementToken> elements =
+ (List<InterfaceStructureElementToken>) elementApi.getAccessor().getAllByFilter(branch, filter,
+ InterfaceStructureElementToken.class);
+ for (InterfaceStructureElementToken element : elements) {
+ PlatformTypeToken platformType = platformApi.getAccessor().getByRelationWithoutId(branch,
+ CoreRelationTypes.InterfaceElementPlatformType_Element, ArtifactId.valueOf(element.getId()),
+ PlatformTypeToken.class);
+ element.setPlatformTypeId(platformType.getId());
+ element.setPlatformTypeName(platformType.getName());
+ }
+ return elements;
+ } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
+ | NoSuchMethodException | SecurityException ex) {
+ return new LinkedList<InterfaceStructureElementToken>();
+ }
+ }
+
+ @Override
+ public Collection<InterfaceStructureElementToken> getElementsOfType(ArtifactId platformTypeId) {
+ try {
+ return elementApi.getAccessor().getAllByRelation(branch,
+ CoreRelationTypes.InterfaceElementPlatformType_PlatformType, platformTypeId,
+ InterfaceStructureElementToken.class);
+ } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
+ | NoSuchMethodException | SecurityException ex) {
+ return new LinkedList<InterfaceStructureElementToken>();
+ }
+ }
+
+ @Override
+ public ElementPosition findElement(ArtifactId elementId) {
+ //Todo at a later date, this endpoint is responsible for returning the relationship tree of an element so that users may return to the main page from an element search.
+ //This ties directly to one of the actions out of a meeting on 6/22, corresponding with new UI, however it could be slightly optional. Likely will be worked during TW19361.
+ return new ElementPosition();
+ }
+
+}
diff --git a/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/internal/InterfaceStructureSearchEndpointImpl.java b/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/internal/InterfaceStructureSearchEndpointImpl.java
new file mode 100644
index 0000000..b68bdae
--- /dev/null
+++ b/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/internal/InterfaceStructureSearchEndpointImpl.java
@@ -0,0 +1,109 @@
+/*********************************************************************
+ * Copyright (c) 2021 Boeing
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Boeing - initial API and implementation
+ **********************************************************************/
+package org.eclipse.osee.mim.internal;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import org.eclipse.osee.framework.core.data.ArtifactId;
+import org.eclipse.osee.framework.core.data.BranchId;
+import org.eclipse.osee.framework.core.data.UserId;
+import org.eclipse.osee.framework.core.enums.CoreRelationTypes;
+import org.eclipse.osee.mim.InterfaceElementApi;
+import org.eclipse.osee.mim.InterfaceElementArrayApi;
+import org.eclipse.osee.mim.InterfacePlatformTypeApi;
+import org.eclipse.osee.mim.InterfaceStructureApi;
+import org.eclipse.osee.mim.InterfaceStructureSearchEndpoint;
+import org.eclipse.osee.mim.types.InterfaceStructureElementToken;
+import org.eclipse.osee.mim.types.InterfaceStructureToken;
+import org.eclipse.osee.mim.types.PlatformTypeToken;
+
+/**
+ * @author Luciano T. Vaglienti
+ */
+public class InterfaceStructureSearchEndpointImpl implements InterfaceStructureSearchEndpoint {
+
+ private final BranchId branch;
+ private final UserId account;
+ private final InterfaceStructureApi interfaceStructureApi;
+ private final InterfaceElementApi interfaceElementApi;
+ private final InterfaceElementArrayApi interfaceElementArrayApi;
+ private final InterfacePlatformTypeApi platformApi;
+
+ public InterfaceStructureSearchEndpointImpl(BranchId branch, UserId account, InterfaceStructureApi interfaceStructureApi, InterfaceElementApi interfaceElementApi, InterfaceElementArrayApi interfaceElementArrayApi, InterfacePlatformTypeApi interfacePlatformTypeApi) {
+ this.account = account;
+ this.branch = branch;
+ this.interfaceStructureApi = interfaceStructureApi;
+ this.interfaceElementApi = interfaceElementApi;
+ this.interfaceElementArrayApi = interfaceElementArrayApi;
+ this.platformApi = interfacePlatformTypeApi;
+ }
+
+ @Override
+ public Collection<InterfaceStructureToken> getAllStructures() {
+ try {
+ List<InterfaceStructureToken> structureList =
+ (List<InterfaceStructureToken>) interfaceStructureApi.getAccessor().getAll(branch,
+ InterfaceStructureToken.class);
+ for (InterfaceStructureToken structure : structureList) {
+ Collection<InterfaceStructureElementToken> elements = new LinkedList<>();
+ elements.addAll(interfaceElementApi.getAccessor().getAllByRelation(branch,
+ CoreRelationTypes.InterfaceStructureContent_Structure, ArtifactId.valueOf(structure.getId()),
+ InterfaceStructureElementToken.class));
+ for (InterfaceStructureElementToken element : elements) {
+ PlatformTypeToken platformType = platformApi.getAccessor().getByRelationWithoutId(branch,
+ CoreRelationTypes.InterfaceElementPlatformType_Element, ArtifactId.valueOf(element.getId()),
+ PlatformTypeToken.class);
+ element.setPlatformTypeId(platformType.getId());
+ element.setPlatformTypeName(platformType.getName());
+ }
+ structure.setElements(elements);
+ }
+
+ return structureList;
+ } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
+ | NoSuchMethodException | SecurityException ex) {
+ return new LinkedList<InterfaceStructureToken>();
+ }
+ }
+
+ @Override
+ public Collection<InterfaceStructureToken> getFilteredStructures(String filter) {
+ try {
+ List<InterfaceStructureToken> structureList =
+ (List<InterfaceStructureToken>) interfaceStructureApi.getAccessor().getAllByFilter(branch, filter,
+ InterfaceStructureToken.class);
+ for (InterfaceStructureToken structure : structureList) {
+ Collection<InterfaceStructureElementToken> elements = new LinkedList<>();
+ elements.addAll(interfaceElementApi.getAccessor().getAllByRelation(branch,
+ CoreRelationTypes.InterfaceStructureContent_Structure, ArtifactId.valueOf(structure.getId()),
+ InterfaceStructureElementToken.class));
+ for (InterfaceStructureElementToken element : elements) {
+ PlatformTypeToken platformType = platformApi.getAccessor().getByRelationWithoutId(branch,
+ CoreRelationTypes.InterfaceElementPlatformType_Element, ArtifactId.valueOf(element.getId()),
+ PlatformTypeToken.class);
+ element.setPlatformTypeId(platformType.getId());
+ element.setPlatformTypeName(platformType.getName());
+ }
+ structure.setElements(elements);
+ }
+
+ return structureList;
+ } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
+ | NoSuchMethodException | SecurityException ex) {
+ return new LinkedList<InterfaceStructureToken>();
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/types/ElementPosition.java b/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/types/ElementPosition.java
new file mode 100644
index 0000000..ae889fc
--- /dev/null
+++ b/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/types/ElementPosition.java
@@ -0,0 +1,72 @@
+/*********************************************************************
+ * Copyright (c) 2021 Boeing
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Boeing - initial API and implementation
+ **********************************************************************/
+package org.eclipse.osee.mim.types;
+
+import java.util.List;
+import org.eclipse.osee.framework.core.data.ArtifactId;
+
+/**
+ * @author Luciano T. Vaglienti
+ */
+public class ElementPosition {
+ //tbd don't know what the structure should look like for returning position of element
+ private List<ArtifactId> messages;
+ private List<ArtifactId> submessages;
+ private List<ArtifactId> structures;
+
+ public ElementPosition() {
+ }
+
+ /**
+ * @return the messages
+ */
+ public List<ArtifactId> getMessages() {
+ return messages;
+ }
+
+ /**
+ * @param messages the messages to set
+ */
+ public void setMessages(List<ArtifactId> messages) {
+ this.messages = messages;
+ }
+
+ /**
+ * @return the submessages
+ */
+ public List<ArtifactId> getSubmessages() {
+ return submessages;
+ }
+
+ /**
+ * @param submessages the submessages to set
+ */
+ public void setSubmessages(List<ArtifactId> submessages) {
+ this.submessages = submessages;
+ }
+
+ /**
+ * @return the structures
+ */
+ public List<ArtifactId> getStructures() {
+ return structures;
+ }
+
+ /**
+ * @param structures the structures to set
+ */
+ public void setStructures(List<ArtifactId> structures) {
+ this.structures = structures;
+ }
+
+}
diff --git a/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/types/InterfaceMessageToken.java b/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/types/InterfaceMessageToken.java
index 6d55a04..52a6d8a 100644
--- a/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/types/InterfaceMessageToken.java
+++ b/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/types/InterfaceMessageToken.java
@@ -44,7 +44,7 @@
@OseeArtifactRequiredAttribute()
@OseeArtifactAttribute(attributeId = 2455059983007225754L)
- private String InterfaceMessageWriteAccess; //required
+ private Boolean InterfaceMessageWriteAccess; //required
@OseeArtifactRequiredAttribute()
@OseeArtifactAttribute(attributeId = 2455059983007225770L)
@@ -69,7 +69,7 @@
this.setInterfaceMessageRate(art.getSoleAttributeAsString(CoreAttributeTypes.InterfaceMessageRate, ""));
this.setInterfaceMessageType(art.getSoleAttributeAsString(CoreAttributeTypes.InterfaceMessageType, ""));
this.setInterfaceMessageWriteAccess(
- art.getSoleAttributeAsString(CoreAttributeTypes.InterfaceMessageWriteAccess, ""));
+ art.getSoleAttributeValue(CoreAttributeTypes.InterfaceMessageWriteAccess, false));
}
public InterfaceMessageToken(Long id, String name) {
@@ -125,14 +125,14 @@
/**
* @return the interfaceMessageWriteAccess
*/
- public String getInterfaceMessageWriteAccess() {
+ public Boolean getInterfaceMessageWriteAccess() {
return InterfaceMessageWriteAccess;
}
/**
* @param interfaceMessageWriteAccess the interfaceMessageWriteAccess to set
*/
- public void setInterfaceMessageWriteAccess(String interfaceMessageWriteAccess) {
+ public void setInterfaceMessageWriteAccess(Boolean interfaceMessageWriteAccess) {
InterfaceMessageWriteAccess = interfaceMessageWriteAccess;
}
diff --git a/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/types/InterfaceStructureElementToken.java b/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/types/InterfaceStructureElementToken.java
index bac99a6..9a3f8d9 100644
--- a/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/types/InterfaceStructureElementToken.java
+++ b/plugins/org.eclipse.osee.mim/src/org/eclipse/osee/mim/types/InterfaceStructureElementToken.java
@@ -34,10 +34,8 @@
@OseeArtifactAttribute(attributeId = 1152921504606847090L)
private String Description;
- @OseeArtifactAttribute(attributeId = 2455059983007225801L)
private Integer InterfaceElementIndexStart;
- @OseeArtifactAttribute(attributeId = 2455059983007225802L)
private Integer InterfaceElementIndexEnd;
private Long PlatformTypeId;
@@ -167,7 +165,7 @@
/**
* @return the platformTypeName
*/
- public String getPlatformTypeName() {
+ public String getPlatformTypeName2() {
return PlatformTypeName;
}
diff --git a/plugins/org.eclipse.osee.web/.gitignore b/plugins/org.eclipse.osee.web/.gitignore
index 86d943a..c86a117 100644
--- a/plugins/org.eclipse.osee.web/.gitignore
+++ b/plugins/org.eclipse.osee.web/.gitignore
@@ -27,7 +27,7 @@
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
-!.vscode/launch.json
+# !.vscode/launch.json don't see any reason to include launch configurations with everyone unless there's heavy usage
!.vscode/extensions.json
.history/*
diff --git a/plugins/org.eclipse.osee.web/angular.json b/plugins/org.eclipse.osee.web/angular.json
index c389a93..0a71c61 100644
--- a/plugins/org.eclipse.osee.web/angular.json
+++ b/plugins/org.eclipse.osee.web/angular.json
@@ -119,6 +119,10 @@
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
+ "codeCoverageExclude": [
+ "src/app/ple/plconfig/types/**",
+ "src/app/ple/plconfig/testing/**"
+ ],
"assets": [
"src/favicon.ico",
"src/assets"
diff --git a/plugins/org.eclipse.osee.web/karma.conf.js b/plugins/org.eclipse.osee.web/karma.conf.js
index 238f8c7..8032413 100644
--- a/plugins/org.eclipse.osee.web/karma.conf.js
+++ b/plugins/org.eclipse.osee.web/karma.conf.js
@@ -38,6 +38,9 @@
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
+ browserConsoleLogOptions: {
+ level: 'log'
+ },
singleRun: false,
restartOnFileChange: true
});
diff --git a/plugins/org.eclipse.osee.web/src/app/app.component.sass b/plugins/org.eclipse.osee.web/src/app/app.component.sass
index 00f056a..6b9157b 100644
--- a/plugins/org.eclipse.osee.web/src/app/app.component.sass
+++ b/plugins/org.eclipse.osee.web/src/app/app.component.sass
@@ -5,4 +5,11 @@
body
height:100%
width:100%
- padding:0px
\ No newline at end of file
+ padding:0px
+.app-div
+ height:100vh
+
+.toolbar-image-left-align
+ display: flex
+ align-items: center
+ justify-content: space-evenly
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/app.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/app.component.spec.ts
index 9a9d29f..9064aae 100644
--- a/plugins/org.eclipse.osee.web/src/app/app.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/app.component.spec.ts
@@ -1,15 +1,28 @@
+import { Component } from '@angular/core';
import { TestBed } from '@angular/core/testing';
+import { MatToolbarModule } from '@angular/material/toolbar';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';
+import { DisplayUserComponent } from './userdata/components/display-user/display-user.component';
+
+
+@Component({
+ selector: 'osee-display-user',
+ template: '<p>Mock Component</p>'
+})
+class MockOseeUserComponent {}
+
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
- RouterTestingModule
+ RouterTestingModule,
+ MatToolbarModule
],
declarations: [
- AppComponent
+ AppComponent,
+ MockOseeUserComponent
],
}).compileComponents();
});
diff --git a/plugins/org.eclipse.osee.web/src/app/interceptors/http/plconfig-set-loading-indicator-interceptor.ts b/plugins/org.eclipse.osee.web/src/app/interceptors/http/plconfig-set-loading-indicator-interceptor.ts
index 3f9c2f4..b6b4358 100644
--- a/plugins/org.eclipse.osee.web/src/app/interceptors/http/plconfig-set-loading-indicator-interceptor.ts
+++ b/plugins/org.eclipse.osee.web/src/app/interceptors/http/plconfig-set-loading-indicator-interceptor.ts
@@ -2,17 +2,19 @@
import { Injectable } from "@angular/core";
import { Observable } from "rxjs";
import { finalize } from "rxjs/operators";
+import { HttpLoadingService } from "src/app/ple/messaging/shared/services/ui/http-loading.service";
import { PlConfigUIStateService } from "src/app/ple/plconfig/services/pl-config-uistate.service";
/** Pass untouched request through to the next request handler. */
@Injectable()
export class PlConfigSetLoadingIndicatorInterceptor implements HttpInterceptor {
requests: HttpRequest<any>[] = [];
- constructor(private uiStateService: PlConfigUIStateService) { };
+ constructor(private uiStateService: PlConfigUIStateService, private messageUIHttpLoadingService:HttpLoadingService) { };
intercept(req: HttpRequest<any>, next: HttpHandler):
Observable<HttpEvent<any>> {
this.requests.push(req);
this.uiStateService.loadingBool = true;
+ this.messageUIHttpLoadingService.loading = true;
return new Observable((observer: { next: (arg0: HttpEvent<any>) => void; error: (arg0: any) => void; complete: () => void; }) => {
const subscription = next.handle(req)
.subscribe(
@@ -44,6 +46,7 @@
this.requests.splice(index, 1);
}
this.uiStateService.loadingBool = this.requests.length > 0;
+ this.messageUIHttpLoadingService.loading = this.requests.length > 0;
}
}
diff --git a/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-string-utils/osee-string-utils-directives/highlight-filtered-text.directive.spec.ts b/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-string-utils/osee-string-utils-directives/highlight-filtered-text.directive.spec.ts
new file mode 100644
index 0000000..1f6d5f8
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-string-utils/osee-string-utils-directives/highlight-filtered-text.directive.spec.ts
@@ -0,0 +1,44 @@
+import { Component, DebugElement, Renderer2, Type } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { HighlightFilteredTextDirective } from './highlight-filtered-text.directive';
+import { By } from '@angular/platform-browser';
+@Component({
+ selector: 'my-test-component',
+ template: '<div appHighlightFilteredText searchTerms="this" text="Hello World This is Text" classToApply="highlightTextClass">Hello World This is Text</div>'
+})
+export class TestComponent {
+}
+
+describe('HighlightFilteredTextDirective', () => {
+ let renderer: Renderer2;
+ let inputEl: DebugElement;
+ let component: TestComponent;
+ let fixture: ComponentFixture<TestComponent>
+ beforeEach((async () => {
+ TestBed.configureTestingModule({
+ declarations: [
+ TestComponent,
+ HighlightFilteredTextDirective,
+ ],
+ }).compileComponents();
+ fixture = TestBed.createComponent(TestComponent);
+ fixture.detectChanges();
+ inputEl = fixture.debugElement;
+ component = fixture.componentInstance;
+ renderer = fixture.componentRef.injector.get(Renderer2 as Type<Renderer2>);
+ }))
+
+
+ it('should create an instance', () => {
+ const directive = new HighlightFilteredTextDirective(inputEl,renderer);
+ expect(directive).toBeTruthy();
+ });
+
+ it('should insert a span of type highlightTextClass', () => {
+ fixture.detectChanges();
+ let nativeEl = inputEl;
+ let spanDe = nativeEl.query(By.css('span'));
+ let span = spanDe.nativeElement;
+ expect(span.classList.contains('highlightTextClass')).toBeTruthy();
+ })
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-string-utils/osee-string-utils-directives/highlight-filtered-text.directive.ts b/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-string-utils/osee-string-utils-directives/highlight-filtered-text.directive.ts
new file mode 100644
index 0000000..d2afc71
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-string-utils/osee-string-utils-directives/highlight-filtered-text.directive.ts
@@ -0,0 +1,29 @@
+import { Directive, ElementRef, Input, Renderer2, SimpleChanges } from '@angular/core';
+
+@Directive({
+ selector: '[appHighlightFilteredText]'
+})
+export class HighlightFilteredTextDirective {
+ @Input() searchTerms: string = "";
+ @Input() text: string = "";
+ @Input() classToApply: string = "";
+ constructor(private el: ElementRef, private renderer: Renderer2) { }
+
+ ngOnChanges(changes: SimpleChanges): void {
+ if (!this.searchTerms || !this.searchTerms.length || !this.classToApply) {
+ this.renderer.setProperty(this.el.nativeElement, 'innerHTML', this.text);
+ return;
+ }
+
+ this.renderer.setProperty(
+ this.el.nativeElement,
+ 'innerHTML',
+ this.getFormattedText()
+ )
+ }
+ getFormattedText() {
+ const re = new RegExp(`(${ this.searchTerms })`, 'i');
+ let returnValue=this.text?.replace(re, `<span class="${this.classToApply}">$1</span>`);
+ return returnValue;
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-string-utils/osee-string-utils-directives/osee-string-utils-directives.module.ts b/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-string-utils/osee-string-utils-directives/osee-string-utils-directives.module.ts
new file mode 100644
index 0000000..931d66c
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-string-utils/osee-string-utils-directives/osee-string-utils-directives.module.ts
@@ -0,0 +1,14 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { HighlightFilteredTextDirective } from './highlight-filtered-text.directive';
+
+
+
+@NgModule({
+ declarations: [HighlightFilteredTextDirective],
+ imports: [
+ CommonModule
+ ],
+ exports: [HighlightFilteredTextDirective]
+})
+export class OseeStringUtilsDirectivesModule { }
diff --git a/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-string-utils/osee-string-utils-pipes/display-truncated-string-with-field-overflow.pipe.spec.ts b/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-string-utils/osee-string-utils-pipes/display-truncated-string-with-field-overflow.pipe.spec.ts
new file mode 100644
index 0000000..1e9a1cf
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-string-utils/osee-string-utils-pipes/display-truncated-string-with-field-overflow.pipe.spec.ts
@@ -0,0 +1,26 @@
+import { DisplayTruncatedStringWithFieldOverflowPipe } from './display-truncated-string-with-field-overflow.pipe';
+
+describe('DisplayTruncatedStringWithFieldOverflowPipe', () => {
+ it('create an instance', () => {
+ const pipe = new DisplayTruncatedStringWithFieldOverflowPipe();
+ expect(pipe).toBeTruthy();
+ });
+
+ it('create a string of length 15+3', () => {
+ const pipe = new DisplayTruncatedStringWithFieldOverflowPipe();
+ const result=pipe.transform("ldaj;fjasdjflkdajgddlagj;aljgdlfjalkejriopetopdoghapohgkldnvz,fjg",...[15])
+ expect(result.length).toEqual(18);
+ });
+
+ it('create a string of length 10+3', () => {
+ const pipe = new DisplayTruncatedStringWithFieldOverflowPipe();
+ const result=pipe.transform("ldaj;fjasdjflkdajgddlagj;aljgdlfjalkejriopetopdoghapohgkldnvz,fjg")
+ expect(result.length).toEqual(13);
+ });
+
+ it('create a string of length 11', () => {
+ const pipe = new DisplayTruncatedStringWithFieldOverflowPipe();
+ const result=pipe.transform("Hello World",15)
+ expect(result.length).toEqual(11);
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-string-utils/osee-string-utils-pipes/display-truncated-string-with-field-overflow.pipe.ts b/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-string-utils/osee-string-utils-pipes/display-truncated-string-with-field-overflow.pipe.ts
new file mode 100644
index 0000000..90a18c2
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-string-utils/osee-string-utils-pipes/display-truncated-string-with-field-overflow.pipe.ts
@@ -0,0 +1,23 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+@Pipe({
+ name: 'displayTruncatedStringWithFieldOverflow'
+})
+export class DisplayTruncatedStringWithFieldOverflowPipe implements PipeTransform {
+ transform(value: string, ...args: number[]): string {
+ let stringLength = 0;
+ if (args[0]!=null && args[0]!=undefined && args[0]>0) {
+ stringLength = args[0];
+ } else {
+ stringLength = 10;
+ }
+ if (value.length < stringLength) {
+ return value;
+ } else {
+ let sub = value.substring(0, stringLength);
+ sub = sub + '...';
+ return sub;
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-string-utils/osee-string-utils-pipes/osee-string-utils-pipes.module.ts b/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-string-utils/osee-string-utils-pipes/osee-string-utils-pipes.module.ts
new file mode 100644
index 0000000..1ebf9a5
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-string-utils/osee-string-utils-pipes/osee-string-utils-pipes.module.ts
@@ -0,0 +1,12 @@
+import { NgModule } from '@angular/core';
+import { DisplayTruncatedStringWithFieldOverflowPipe } from './display-truncated-string-with-field-overflow.pipe';
+
+
+
+@NgModule({
+ declarations: [DisplayTruncatedStringWithFieldOverflowPipe],
+ imports: [
+ ],
+ exports:[DisplayTruncatedStringWithFieldOverflowPipe]
+})
+export class OseeStringUtilsPipesModule { }
diff --git a/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-string-utils/osee-string-utils.module.ts b/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-string-utils/osee-string-utils.module.ts
new file mode 100644
index 0000000..cb5ecaf
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-string-utils/osee-string-utils.module.ts
@@ -0,0 +1,17 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { OseeStringUtilsPipesModule } from './osee-string-utils-pipes/osee-string-utils-pipes.module';
+import { OseeStringUtilsDirectivesModule } from './osee-string-utils-directives/osee-string-utils-directives.module';
+
+
+
+@NgModule({
+ declarations: [],
+ imports: [
+ CommonModule,
+ OseeStringUtilsPipesModule,
+ OseeStringUtilsDirectivesModule
+ ],
+ exports: [OseeStringUtilsModule, OseeStringUtilsDirectivesModule]
+})
+export class OseeStringUtilsModule { }
diff --git a/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-utils.module.ts b/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-utils.module.ts
new file mode 100644
index 0000000..75305f3
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/osee-utils/osee-utils.module.ts
@@ -0,0 +1,15 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { OseeStringUtilsModule } from './osee-string-utils/osee-string-utils.module';
+
+
+
+@NgModule({
+ declarations: [],
+ imports: [
+ CommonModule,
+ OseeStringUtilsModule
+ ],
+ exports:[OseeStringUtilsModule]
+})
+export class OseeUtilsModule { }
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-element-dialog/add-element-dialog.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-element-dialog/add-element-dialog.component.html
new file mode 100644
index 0000000..499b71d
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-element-dialog/add-element-dialog.component.html
@@ -0,0 +1,77 @@
+<h1 mat-dialog-title>Add Element to {{data.name}}</h1>
+<mat-horizontal-stepper #stepper class ="new-submessage-stepper">
+ <mat-step label="Select Element options" #step1>
+ <div style="display:flex; flex-direction:row; justify-content: space-evenly; align-items: baseline;">
+ <button mat-raised-button color="primary" style="width:100%;" matStepperNext (click)="createNew()">Create new Element</button>
+ <p style="width:100%; text-align:center;">or</p>
+ <mat-form-field style="width:100%;">
+ <mat-label>Select a Element to Add to Structure</mat-label>
+ <mat-select [(ngModel)]="data.element" (selectionChange)="storeId($event.value)">
+ <mat-option *ngFor="let option of (availableElements|async)" [value]="option" [id]="option!==undefined && option.id !==undefined ? option.id :''" >
+ {{option.name}}
+ </mat-option>
+ </mat-select>
+ </mat-form-field>
+ </div>
+ <button mat-raised-button color="primary" *ngIf="data.element?.id && data.element?.id!=='-1'" (click)="moveToReview(stepper)">Proceed to Review</button>
+ </mat-step>
+ <mat-step label="Define element" #step2>
+ <div style="display:flex; flex-direction:column">
+ <mat-form-field>
+ <mat-label>Name</mat-label>
+ <input matInput [(ngModel)]="data.element.name" required>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>Description</mat-label>
+ <input matInput [(ngModel)]="data.element.description" required>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>Notes</mat-label>
+ <input matInput [(ngModel)]="data.element.notes">
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>Start Index</mat-label>
+ <input type="number" matInput [(ngModel)]="data.element.interfaceElementIndexStart" required>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>End Index</mat-label>
+ <input type="number" matInput [(ngModel)]="data.element.interfaceElementIndexEnd" required>
+ </mat-form-field>
+ <mat-slide-toggle [(ngModel)]="data.element.interfaceElementAlterable" labelPosition='before'>
+ Alterable
+ </mat-slide-toggle>
+ <mat-form-field style="width:100%;">
+ <mat-label>Select a Platform Type</mat-label>
+ <mat-select [(ngModel)]="data.type">
+ <mat-option *ngFor="let option of (availableTypes|async)" [value]="option" [id]="option!==undefined && option.id !==undefined ? option.id :''" >
+ {{option.name}}
+ </mat-option>
+ </mat-select>
+ </mat-form-field>
+ </div>
+ <button mat-raised-button matStepperPrevious>Back</button>
+ <button mat-raised-button color="primary" *ngIf="data.element.name.length>0 &&
+ data.element.description.length>0 &&
+ data.type.name.length>0 &&
+ +data.type.id>0" matStepperNext>Next</button>
+ </mat-step>
+ <mat-step label="Review" #step3>
+ <div style="display:flex;flex-direction:column">
+ An element will be related to:
+ <mat-label>{{data.name}}</mat-label> with the following properties:
+ <mat-label>Element Name: {{data.element.name}}</mat-label>
+ <mat-label>Element Description: {{data.element.description}}</mat-label>
+ <mat-label>Element Notes: {{data.element.notes}}</mat-label>
+ <mat-label>Element Start Index: {{data.element.interfaceElementIndexStart}}</mat-label>
+ <mat-label>Element End Index: {{data.element.interfaceElementIndexEnd}}</mat-label>
+ <mat-label>Element Alterable: {{data.element.interfaceElementAlterable}}</mat-label>
+ <mat-label>Platform Type: {{data.type.name}}</mat-label>
+ </div>
+ <mat-dialog-actions align="end">
+ <button mat-button matStepperPrevious>Back</button>
+ <button mat-raised-button color="primary" [mat-dialog-close]="data">
+ Ok
+ </button>
+ </mat-dialog-actions>
+ </mat-step>
+</mat-horizontal-stepper>
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-element-dialog/add-element-dialog.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-element-dialog/add-element-dialog.component.sass
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-element-dialog/add-element-dialog.component.sass
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-element-dialog/add-element-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-element-dialog/add-element-dialog.component.spec.ts
new file mode 100644
index 0000000..adc3a58
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-element-dialog/add-element-dialog.component.spec.ts
@@ -0,0 +1,59 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatSelectModule } from '@angular/material/select';
+import { MatSlideToggleModule } from '@angular/material/slide-toggle';
+import { MatStepperModule } from '@angular/material/stepper';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { AddElementDialog } from '../../types/AddElementDialog';
+
+import { AddElementDialogComponent } from './add-element-dialog.component';
+
+describe('AddElementDialogComponent', () => {
+ let component: AddElementDialogComponent;
+ let fixture: ComponentFixture<AddElementDialogComponent>;
+ let dialogData: AddElementDialog = {
+ id: '12345',
+ name: 'structure',
+ type: { id: '', name: '' },
+ element: {
+ id: '-1',
+ name: '',
+ description: '',
+ notes: '',
+ interfaceElementAlterable: true,
+ interfaceElementIndexEnd: 0,
+ interfaceElementIndexStart:0
+ }
+ }
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports:[HttpClientTestingModule,MatStepperModule,MatDialogModule,MatButtonModule,FormsModule,MatFormFieldModule,MatSelectModule,MatInputModule,MatSlideToggleModule,NoopAnimationsModule],
+ declarations: [AddElementDialogComponent],
+ providers: [{
+ provide: MatDialogRef, useValue: {
+
+ }
+ },
+ {
+ provide: MAT_DIALOG_DATA, useValue: dialogData
+ }]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(AddElementDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-element-dialog/add-element-dialog.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-element-dialog/add-element-dialog.component.ts
new file mode 100644
index 0000000..875a047
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-element-dialog/add-element-dialog.component.ts
@@ -0,0 +1,37 @@
+import { Component, Inject, OnInit } from '@angular/core';
+import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatStepper } from '@angular/material/stepper';
+import { CurrentStateService } from '../../services/current-state.service';
+import { AddElementDialog } from '../../types/AddElementDialog';
+import { element } from '../../types/element';
+
+@Component({
+ selector: 'osee-messaging-add-element-dialog',
+ templateUrl: './add-element-dialog.component.html',
+ styleUrls: ['./add-element-dialog.component.sass']
+})
+export class AddElementDialogComponent implements OnInit {
+
+ availableElements = this.structures.availableElements;
+ storedId: string = '-1';
+ availableTypes= this.structures.types;
+ constructor(private structures:CurrentStateService,public dialogRef: MatDialogRef<AddElementDialogComponent>, @Inject(MAT_DIALOG_DATA) public data: AddElementDialog) { }
+
+ ngOnInit(): void {
+ }
+
+ createNew() {
+ this.data.element.id = '-1';
+ }
+ storeId(value: element) {
+ this.storedId = value.id || '-1';
+ }
+
+ moveToStep(index: number, stepper: MatStepper) {
+ stepper.selectedIndex = index - 1;
+ }
+ moveToReview(stepper: MatStepper) {
+ this.data.element.id = this.storedId;
+ this.moveToStep(3, stepper);
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-structure-dialog/add-structure-dialog.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-structure-dialog/add-structure-dialog.component.html
new file mode 100644
index 0000000..76d66ff
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-structure-dialog/add-structure-dialog.component.html
@@ -0,0 +1,66 @@
+<h1 mat-dialog-title>Add Structure to {{data.name}}</h1>
+<mat-horizontal-stepper #stepper class ="new-submessage-stepper">
+ <mat-step label="Select Structure options" #step1>
+ <div style="display:flex; flex-direction:row; justify-content: space-evenly; align-items: baseline;">
+ <button mat-raised-button color="primary" style="width:100%;" matStepperNext (click)="createNew()">Create new Structure</button>
+ <p style="width:100%; text-align:center;">or</p>
+ <mat-form-field style="width:100%;">
+ <mat-label>Select a Structure to Add to Sub Message</mat-label>
+ <mat-select [(ngModel)]="data.structure" (selectionChange)="storeId($event.value)">
+ <mat-option *ngFor="let option of (availableStructures|async)" [value]="option" [id]="option!==undefined && option.id !==undefined ? option.id :''" >
+ {{option.name}}
+ </mat-option>
+ </mat-select>
+ </mat-form-field>
+ </div>
+ <button mat-raised-button color="primary" *ngIf="data.structure?.id && data.structure?.id!=='-1'" (click)="moveToReview(stepper)">Proceed to Review</button>
+ </mat-step>
+ <mat-step label="Define Structure" #step2>
+ <div style="display:flex; flex-direction:column">
+ <mat-form-field>
+ <mat-label>Name</mat-label>
+ <input matInput [(ngModel)]="data.structure.name" required>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>Description</mat-label>
+ <input matInput [(ngModel)]="data.structure.description" required>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>Max Simultaneity</mat-label>
+ <input matInput [(ngModel)]="data.structure.interfaceMaxSimultaneity" required>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>Min Simultaneity</mat-label>
+ <input matInput [(ngModel)]="data.structure.interfaceMinSimultaneity" required>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>Task File Type</mat-label>
+ <input type="number" matInput [(ngModel)]="data.structure.interfaceTaskFileType" required>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>Category</mat-label>
+ <input matInput [(ngModel)]="data.structure.interfaceStructureCategory" required>
+ </mat-form-field>
+ </div>
+ <button mat-raised-button matStepperPrevious>Back</button>
+ <button mat-raised-button color="primary" *ngIf="data.structure.name.length>0 && data.structure.description.length>0 && data.structure.interfaceMaxSimultaneity.length >0 && data.structure.interfaceMinSimultaneity.length >0 && data.structure.interfaceTaskFileType!==undefined && data.structure.interfaceStructureCategory.length>0" matStepperNext>Next</button>
+ </mat-step>
+ <mat-step label="Review" #step3>
+ <div style="display:flex;flex-direction:column">
+ A structure will be related to:
+ <mat-label>{{data.name}}</mat-label> with the following properties:
+ <mat-label>Structure Name: {{data.structure.name}}</mat-label>
+ <mat-label>Structure Description: {{data.structure.description}}</mat-label>
+ <mat-label>Structure Max Simultaneity: {{data.structure.interfaceMaxSimultaneity}}</mat-label>
+ <mat-label>Structure Min Simultaneity: {{data.structure.interfaceMinSimultaneity}}</mat-label>
+ <mat-label>Structure Task File Type: {{data.structure.interfaceTaskFileType}}</mat-label>
+ <mat-label>Structure Category: {{data.structure.interfaceStructureCategory}}</mat-label>
+ </div>
+ <mat-dialog-actions align="end">
+ <button mat-button matStepperPrevious>Back</button>
+ <button mat-raised-button color="primary" [mat-dialog-close]="data">
+ Ok
+ </button>
+ </mat-dialog-actions>
+ </mat-step>
+</mat-horizontal-stepper>
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-structure-dialog/add-structure-dialog.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-structure-dialog/add-structure-dialog.component.sass
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-structure-dialog/add-structure-dialog.component.sass
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-structure-dialog/add-structure-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-structure-dialog/add-structure-dialog.component.spec.ts
new file mode 100644
index 0000000..8164d0a
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-structure-dialog/add-structure-dialog.component.spec.ts
@@ -0,0 +1,90 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatSelectModule } from '@angular/material/select';
+import { MatSlideToggleModule } from '@angular/material/slide-toggle';
+import { MatStepperModule } from '@angular/material/stepper';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { AddStructureDialog } from '../../types/AddStructureDialog';
+import { structure } from '../../types/structure';
+
+import { AddStructureDialogComponent } from './add-structure-dialog.component';
+
+describe('AddStructureDialogComponent', () => {
+ let component: AddStructureDialogComponent;
+ let fixture: ComponentFixture<AddStructureDialogComponent>;
+ let dialogRef = jasmine.createSpyObj('MatDialogRef', ['close']);
+ let dialogData: AddStructureDialog = {
+ id: '123456',
+ name: 'submessage',
+ structure: {
+ id: '',
+ name: '',
+ description: '',
+ elements: [],
+ interfaceMaxSimultaneity: "1",
+ interfaceMinSimultaneity: "0",
+ interfaceStructureCategory: "",
+ interfaceTaskFileType:0
+ }
+ }
+ let dummyStructure: structure = {
+ id: '10',
+ name: '',
+ description: '',
+ elements: [],
+ interfaceMaxSimultaneity: '1',
+ interfaceMinSimultaneity: '0',
+ interfaceStructureCategory: '',
+ interfaceTaskFileType:0
+ }
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports:[HttpClientTestingModule,MatStepperModule,MatDialogModule,MatButtonModule,FormsModule,MatFormFieldModule,MatSelectModule,MatInputModule,MatSlideToggleModule,NoopAnimationsModule],
+ declarations: [AddStructureDialogComponent],
+ providers:[{provide:MAT_DIALOG_DATA,useValue:dialogData},{provide:MatDialogRef,useValue:dialogRef}]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(AddStructureDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should movetoStep', () => {
+ let stepper = jasmine.createSpyObj('stepper', {}, { selectedIndex: 0 });
+ spyOn(stepper, 'selectedIndex').and.callThrough();
+ component.moveToStep(3, stepper);
+ expect(stepper.selectedIndex).toEqual(0);
+ });
+
+ it('should create new by setting id to -1', () => {
+ component.createNew();
+ expect(component.data.structure.id).toEqual('-1');
+ });
+
+ it('should store the id', () => {
+ component.storeId(dummyStructure);
+ expect(component.storedId).toEqual('10');
+ });
+
+ it('should movetoStep 3', () => {
+ let stepper = jasmine.createSpyObj('stepper', {}, { selectedIndex: 0 });
+ spyOn(stepper, 'selectedIndex').and.callThrough();
+ let spy = spyOn(component, 'moveToStep').and.stub();
+ component.moveToReview(stepper);
+ expect(spy).toHaveBeenCalled();
+ expect(spy).toHaveBeenCalledWith(3, stepper);
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-structure-dialog/add-structure-dialog.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-structure-dialog/add-structure-dialog.component.ts
new file mode 100644
index 0000000..430135a
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/add-structure-dialog/add-structure-dialog.component.ts
@@ -0,0 +1,38 @@
+import { Component, Inject, OnInit } from '@angular/core';
+import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatStepper } from '@angular/material/stepper';
+import { CurrentStateService } from '../../services/current-state.service';
+import { AddStructureDialog } from '../../types/AddStructureDialog';
+import { structure } from '../../types/structure';
+
+@Component({
+ selector: 'osee-messaging-add-structure-dialog',
+ templateUrl: './add-structure-dialog.component.html',
+ styleUrls: ['./add-structure-dialog.component.sass']
+})
+export class AddStructureDialogComponent implements OnInit {
+
+ availableStructures = this.structures.availableStructures;
+ storedId:string='-1'
+ constructor(private structures:CurrentStateService,public dialogRef: MatDialogRef<AddStructureDialogComponent>, @Inject(MAT_DIALOG_DATA) public data: AddStructureDialog) { }
+
+ ngOnInit(): void {
+ }
+
+ moveToStep(index: number, stepper: MatStepper) {
+ stepper.selectedIndex = index - 1;
+ }
+
+ createNew() {
+ this.data.structure.id = '-1';
+ }
+
+ storeId(value: structure) {
+ this.storedId = value.id || '-1';
+ }
+
+ moveToReview(stepper: MatStepper) {
+ this.data.structure.id = this.storedId;
+ this.moveToStep(3, stepper);
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/edit-structure-field/edit-structure-field.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/edit-structure-field/edit-structure-field.component.html
new file mode 100644
index 0000000..19125ae
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/edit-structure-field/edit-structure-field.component.html
@@ -0,0 +1,4 @@
+<mat-form-field>
+ <mat-label>{{header|convertMessageInterfaceTitlesToString}}</mat-label>
+ <input matInput [(ngModel)]="value" (ngModelChange)="updateStructure(header,value)">
+</mat-form-field>
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/edit-structure-field/edit-structure-field.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/edit-structure-field/edit-structure-field.component.sass
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/edit-structure-field/edit-structure-field.component.sass
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/edit-structure-field/edit-structure-field.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/edit-structure-field/edit-structure-field.component.spec.ts
new file mode 100644
index 0000000..1cd85b5
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/edit-structure-field/edit-structure-field.component.spec.ts
@@ -0,0 +1,33 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatSelectModule } from '@angular/material/select';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { SharedMessagingModule } from '../../../shared/shared-messaging.module';
+
+import { EditStructureFieldComponent } from './edit-structure-field.component';
+
+describe('EditStructureFieldComponent', () => {
+ let component: EditStructureFieldComponent;
+ let fixture: ComponentFixture<EditStructureFieldComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports:[HttpClientTestingModule,NoopAnimationsModule,FormsModule,MatFormFieldModule,MatInputModule,MatSelectModule,SharedMessagingModule],
+ declarations: [ EditStructureFieldComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(EditStructureFieldComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/edit-structure-field/edit-structure-field.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/edit-structure-field/edit-structure-field.component.ts
new file mode 100644
index 0000000..4ac11bf
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/edit-structure-field/edit-structure-field.component.ts
@@ -0,0 +1,50 @@
+import { Component, Input, OnInit } from '@angular/core';
+import { Subject } from 'rxjs';
+import { share, debounceTime, distinctUntilChanged, map, tap, switchMap } from 'rxjs/operators';
+import { CurrentStateService } from '../../services/current-state.service';
+
+interface structure {
+ id: string,
+ name: string,
+ description: string,
+ interfaceMaxSimultaneity: string,
+ interfaceMinSimultaneity: string,
+ interfaceTaskFileType: number,
+ interfaceStructureCategory: string
+}
+@Component({
+ selector: 'osee-messaging-edit-structure-field',
+ templateUrl: './edit-structure-field.component.html',
+ styleUrls: ['./edit-structure-field.component.sass']
+})
+export class EditStructureFieldComponent implements OnInit {
+
+ @Input() structureId!: string ;
+ @Input() header: string = '';
+ @Input() value: string = '';
+ private _value: Subject<string> = new Subject();
+ _structure: Partial<structure> = {
+ id:this.structureId
+ };
+ private _sendValue = this._value.pipe(
+ share(),
+ debounceTime(500),
+ distinctUntilChanged(),
+ map((x: any) => this._structure[this.header as keyof structure] = x),
+ tap(() => {
+ this._structure.id = this.structureId;
+ }),
+ switchMap(val=>this.structureService.partialUpdateStructure(this._structure))
+ )
+ constructor (private structureService: CurrentStateService) {
+ this._sendValue.subscribe();
+ }
+
+ ngOnInit(): void {
+ }
+
+ updateStructure(header: string, value: string) {
+ this._value.next(value);
+ }
+
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/edit-element-field/edit-element-field.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/edit-element-field/edit-element-field.component.html
new file mode 100644
index 0000000..dd730db
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/edit-element-field/edit-element-field.component.html
@@ -0,0 +1,24 @@
+<mat-form-field>
+ <mat-label>{{header|convertMessageInterfaceTitlesToString}}</mat-label>
+ <input matInput [(ngModel)]="value" (ngModelChange)="updateElement(header,value)" *ngIf="header!=='platformTypeName2'">
+ <ng-container *ngIf="header==='name'">
+ <ng-container *ngIf="elementEnd-elementStart>0">
+ <p matSuffix>
+ {{"["+elementStart+"..."+elementEnd+"]"}}
+ </p>
+ </ng-container>
+ </ng-container>
+ <ng-container *ngIf="header==='platformTypeName2'">
+ <!-- <mat-select [(ngModel)]="value" (selectionChange)="updateType($event.value)">
+ <mat-option *ngFor="let option of (availableTypes|async)" [value]="option.id" [id]="option!==undefined && option.id !==undefined ? option.id :''" >
+ {{option.name}}
+ </mat-option>
+ </mat-select> -->
+ <input matInput type="search" [(ngModel)]="value" [matAutocomplete]="auto" (ngModelChange)="updateTypeAhead(value)">
+ <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete" (optionSelected)="updateType($event.option.value)">
+ <mat-option *ngFor="let option of filteredTypes | async" [value]="option.id" [id]="option!==undefined && option.id !==undefined ? option.id :''">
+ {{option.name}}
+ </mat-option>
+ </mat-autocomplete>
+ </ng-container>
+</mat-form-field>
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/edit-element-field/edit-element-field.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/edit-element-field/edit-element-field.component.sass
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/edit-element-field/edit-element-field.component.sass
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/edit-element-field/edit-element-field.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/edit-element-field/edit-element-field.component.spec.ts
new file mode 100644
index 0000000..003f769
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/edit-element-field/edit-element-field.component.spec.ts
@@ -0,0 +1,33 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatSelectModule } from '@angular/material/select';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { SharedMessagingModule } from 'src/app/ple/messaging/shared/shared-messaging.module';
+
+import { EditElementFieldComponent } from './edit-element-field.component';
+
+describe('EditElementFieldComponent', () => {
+ let component: EditElementFieldComponent;
+ let fixture: ComponentFixture<EditElementFieldComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports:[HttpClientTestingModule,NoopAnimationsModule,FormsModule,MatFormFieldModule,MatInputModule,MatSelectModule,SharedMessagingModule],
+ declarations: [ EditElementFieldComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(EditElementFieldComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/edit-element-field/edit-element-field.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/edit-element-field/edit-element-field.component.ts
new file mode 100644
index 0000000..16ea6bc
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/edit-element-field/edit-element-field.component.ts
@@ -0,0 +1,75 @@
+import { Component, Input, OnInit } from '@angular/core';
+import { combineLatest } from 'rxjs';
+import { BehaviorSubject, from, of, Subject } from 'rxjs';
+import { share, debounceTime, distinctUntilChanged, map, tap, switchMap, mergeMap, filter, scan, repeatWhen } from 'rxjs/operators';
+import { CurrentStateService } from '../../../services/current-state.service';
+import { element } from '../../../types/element';
+import { PlatformType } from '../../../types/platformtype';
+
+@Component({
+ selector: 'osee-messaging-edit-element-field',
+ templateUrl: './edit-element-field.component.html',
+ styleUrls: ['./edit-element-field.component.sass']
+})
+export class EditElementFieldComponent implements OnInit {
+ availableTypes = this.structureService.types;
+ @Input() structureId: string = '';
+ @Input() elementId: string = '';
+ @Input() header: string = '';
+ @Input() value: any = '';
+ @Input() elementStart: number =0;
+ @Input() elementEnd: number = 0;
+ private _value: Subject<string> = new Subject();
+ _element: Partial<element> = {
+ id:this.elementId
+ };
+ private _typeValue: BehaviorSubject<any> = new BehaviorSubject(this.value);
+ private _sendValue = this._value.pipe(
+ share(),
+ debounceTime(500),
+ distinctUntilChanged(),
+ map((x: any) => this._element[this.header as keyof element] = x),
+ tap(() => {
+ this._element.id = this.elementId;
+ }),
+ switchMap(val=>this.structureService.partialUpdateElement(this._element,this.structureId))
+ )
+ filteredTypes = combineLatest(this._typeValue,this.availableTypes).pipe(
+ switchMap(val => from(val[1]).pipe(
+ filter((val: PlatformType) => val.name.toLowerCase().includes(this.value.toLowerCase())),
+ scan((acc, curr) => [...acc, curr], [] as PlatformType[]),
+ )),
+ )
+ private _type: Subject<string> = new Subject();
+ private _sendType = this._type.pipe(
+ share(),
+ debounceTime(500),
+ distinctUntilChanged(),
+ switchMap(val=>this.structureService.changeElementPlatformType(this.structureId,this.elementId,val))
+ )
+
+ constructor (private structureService: CurrentStateService) {
+ this._sendValue.subscribe();
+ this._sendType.subscribe();
+ }
+
+ ngOnInit(): void {
+ }
+
+ updateElement(header: string, value: string) {
+ this._value.next(value);
+ }
+
+ updateType(value: string) {
+ this._type.next(value);
+ }
+
+ log(value: any) {
+ console.log(value);
+ }
+
+ updateTypeAhead(value: any) {
+ this._typeValue.next(value);
+ }
+
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/sub-element-table.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/sub-element-table.component.html
new file mode 100644
index 0000000..2f151d0
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/sub-element-table.component.html
@@ -0,0 +1,56 @@
+<table mat-table [dataSource]="dataSource" class="message-element-interface-table-view-element mat-elevation-z9 message-element-interface-table-view-width-100">
+ <ng-container [matColumnDef]="subHeader" *ngFor="let subHeader of subMessageHeaders;let j=index;trackBy:valueTracker">
+ <th mat-header-cell *matHeaderCellDef class="message-element-interface-table-view-sub-message-header">{{subHeader | convertMessageInterfaceTitlesToString}}</th>
+ <td mat-cell *matCellDef="let value" class="message-element-interface-table-center">
+ <ng-container *ngIf="editMode===true; else no_edit">
+ <ng-container *ngIf="subHeader==='platformTypeName2'">
+ <osee-messaging-edit-element-field [header]="subHeader" [structureId]="element.id" [elementId]="value['id']" [elementStart]="value['interfaceElementIndexStart']" [elementEnd]="value['interfaceElementIndexEnd']" [value]="value['platformTypeName2'].toString()"></osee-messaging-edit-element-field>
+ </ng-container>
+ <ng-container *ngIf="subHeader!=='platformTypeName2'">
+ <osee-messaging-edit-element-field [header]="subHeader" [structureId]="element.id" [elementId]="value['id']" [elementStart]="value['interfaceElementIndexStart']" [elementEnd]="value['interfaceElementIndexEnd']" [value]="value[subHeader]"></osee-messaging-edit-element-field>
+ </ng-container>
+ </ng-container>
+ <ng-template #no_edit>
+ <div *ngIf="subHeader==='description'||subHeader==='EnumLiteralsDesc'||subHeader==='Notes'" [matTooltip]="value[subHeader]" [matTooltipDisabled]="value[subHeader].length<15" appHighlightFilteredText [searchTerms]="filter" [text]="value[subHeader] | displayTruncatedStringWithFieldOverflow:15" classToApply="ple-message-element-interface-table-highlighted-text">
+ </div>
+ <div *ngIf="subHeader!=='Notes' &&subHeader!=='platformTypeName2' && subHeader!=='name' && subHeader !=='description'" appHighlightFilteredText [searchTerms]="filter" [text]="value[subHeader]" classToApply="ple-message-element-interface-table-highlighted-text">
+ <!-- subHeader!=='description'&&subHeader!=='EnumLiteralsDesc'&& -->
+ {{value[subHeader]}}
+ </div>
+ <div *ngIf="subHeader==='name'">
+ <ng-container *ngIf="value['interfaceElementIndexEnd']-value['interfaceElementIndexStart']>0">
+ {{value[subHeader]+"["+value['interfaceElementIndexStart']+"..."+value['interfaceElementIndexEnd']+"]"}}
+ </ng-container>
+ <ng-container *ngIf="value['interfaceElementIndexEnd']-value['interfaceElementIndexStart']<=0">
+ {{value[subHeader]}}
+ </ng-container>
+ </div>
+ <ng-container *ngIf="subHeader==='platformTypeName2'">
+ <button mat-stroked-button (click)="navigateTo(value[subHeader])" (contextmenu)="openMenu($event,value[subHeader])">
+ {{value[subHeader]}}
+ </button>
+ </ng-container>
+ </ng-template>
+ </td>
+ </ng-container>
+ <ng-container matColumnDef="footer">
+ <td mat-footer-cell *matFooterCellDef [attr.colspan]="subMessageHeaders.length" style="text-align:right">
+ <ng-container *ngIf="editMode===true;">
+ <button mat-mini-fab color="primary" (click)="openAddElementDialog()">+</button>
+ </ng-container>
+ </td>
+ </ng-container>
+ <tr mat-header-row *matHeaderRowDef="subMessageHeaders; sticky:true"></tr>
+ <tr mat-row *matRowDef= "let row2; columns: subMessageHeaders; let k=index;"
+ [ngClass]="k%2===0? 'message-table-sub-element-row-even':'message-table-sub-element-row-odd'"></tr>
+ <tr mat-footer-row *matFooterRowDef="['footer']"></tr>
+</table>
+<mat-menu #contextMenu="matMenu">
+ <ng-template matMenuContent let-location="location">
+ <button mat-menu-item (click)="navigateToInNewTab(location)"> Open in new tab</button>
+ </ng-template>
+</mat-menu>
+<div style="visibility: hidden; position: fixed;"
+[style.left]="menuPosition.x"
+[style.top]="menuPosition.y"
+[matMenuTriggerFor]="contextMenu"></div>
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/sub-element-table.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/sub-element-table.component.sass
new file mode 100644
index 0000000..b73b07c
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/sub-element-table.component.sass
@@ -0,0 +1,23 @@
+.message-element-interface-table-view-sub-message-header
+ font:
+ weight: 500
+ // size: 12px
+ text:
+ align: center
+.message-element-interface-table-center
+ text-align: center
+ // text:
+ // align: center
+.message-element-interface-table-view-width-100
+ width: 100%
+body
+ width: 100%
+::host
+ display: block
+ width: 100%
+ max-height: 10%
+.new-element-button
+ z-index: 10
+ position: fixed
+ bottom: 3%
+ right: 2%
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/sub-element-table.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/sub-element-table.component.spec.ts
new file mode 100644
index 0000000..ecf4997
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/sub-element-table.component.spec.ts
@@ -0,0 +1,109 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { SimpleChange } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatTableModule } from '@angular/material/table';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { ActivatedRoute, convertToParamMap, Router } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+import { of } from 'rxjs';
+import { OseeStringUtilsDirectivesModule } from 'src/app/osee-utils/osee-string-utils/osee-string-utils-directives/osee-string-utils-directives.module';
+import { OseeStringUtilsPipesModule } from 'src/app/osee-utils/osee-string-utils/osee-string-utils-pipes/osee-string-utils-pipes.module';
+import { ConvertMessageInterfaceTitlesToStringPipe } from '../../../shared/pipes/convert-message-interface-titles-to-string.pipe';
+import { SharedMessagingModule } from '../../../shared/shared-messaging.module';
+import { EditElementFieldComponent } from './edit-element-field/edit-element-field.component';
+
+import { SubElementTableComponent } from './sub-element-table.component';
+
+describe('SubElementTableComponent', () => {
+ let component: SubElementTableComponent;
+ let fixture: ComponentFixture<SubElementTableComponent>;
+ let expectedData = [
+ {
+ beginWord: 'BEGIN',
+ endWord: "END",
+ BeginByte: '0',
+ EndByte: '32',
+ Sequence: 'Sequence',
+ ElementName: 'name1',
+ Units: 'N/A',
+ MinValue: '0',
+ MaxValue: '1',
+ AlterableAfterCreationValid: false,
+ Description: "A description",
+ EnumLiteralsDesc: "Description of enum literals",
+ Notes: "Notes go here",
+ DefaultValue: "0",
+ isArray: false,
+ },
+ {
+ beginWord: 'Hello',
+ endWord: "World",
+ BeginByte: '0',
+ EndByte: '32',
+ Sequence: 'Sequence',
+ ElementName: 'name2',
+ Units: 'N/A',
+ MinValue: '0',
+ MaxValue: '1',
+ AlterableAfterCreationValid: false,
+ Description: "A description",
+ EnumLiteralsDesc: "Description of enum literals",
+ Notes: "Notes go here",
+ DefaultValue: "0",
+ isArray: false,
+ }
+ ];
+ let router: any;
+
+ beforeEach(async () => {
+ router = jasmine.createSpyObj('Router', ['navigate', 'createUrlTree', 'serializeUrl'],['paramMap']);
+ await TestBed.configureTestingModule({
+ imports:[MatTableModule,MatFormFieldModule,MatInputModule,FormsModule,NoopAnimationsModule, OseeStringUtilsDirectivesModule, OseeStringUtilsPipesModule, RouterTestingModule,SharedMessagingModule, HttpClientTestingModule],
+ declarations: [SubElementTableComponent, ConvertMessageInterfaceTitlesToStringPipe, EditElementFieldComponent],
+ providers: [{ provide: Router, useValue: router }, {
+ provide: ActivatedRoute, useValue: {
+ paramMap: of(convertToParamMap({ branchId: "10",branchType:"working" }))
+ }}]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(SubElementTableComponent);
+ component = fixture.componentInstance;
+ component.data = expectedData;
+ component.dataSource.filter="name1"
+ component.filter="element: name1"
+ //fixture.detectChanges();
+ });
+
+ it('should create',async () => {
+ fixture.detectChanges();
+ await fixture.whenStable();
+ expect(component).toBeTruthy();
+ expect(component.data === expectedData).toBeTruthy();
+ expect(component.filter === 'element: name1').toBeTruthy();
+ expect(component.dataSource.filter === 'name1').toBeTruthy();
+ });
+ it('should update filter on changes',async () => {
+ fixture.detectChanges();
+ await fixture.whenStable();
+ component.filter = "element: name2";
+ component.ngOnChanges({
+ data: new SimpleChange(expectedData, expectedData, false),
+ filter: new SimpleChange('element: name1', 'element: name2', false)
+ });
+ await fixture.whenStable();
+ expect(component.dataSource.filter === 'name2').toBeTruthy();
+ expect(component).toBeTruthy();
+ });
+
+ it('should navigate to //types/10', () => {
+ component.navigateTo("10");
+ expect(router.navigate).toHaveBeenCalledWith(['','','types','10'],{relativeTo: undefined, queryParamsHandling:'merge'});
+ });
+
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/sub-element-table.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/sub-element-table.component.ts
new file mode 100644
index 0000000..3626f4e
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/components/sub-element-table/sub-element-table.component.ts
@@ -0,0 +1,120 @@
+import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core';
+import { MatDialog } from '@angular/material/dialog';
+import { MatMenuTrigger } from '@angular/material/menu';
+import { MatTableDataSource } from '@angular/material/table';
+import { ActivatedRoute, Router } from '@angular/router';
+import { iif } from 'rxjs';
+import { forkJoin, of } from 'rxjs';
+import { filter, first, map, mergeMap, switchMap, take } from 'rxjs/operators';
+import { CurrentStateService } from '../../services/current-state.service';
+import { AddElementDialog } from '../../types/AddElementDialog';
+import { AddElementDialogComponent } from '../add-element-dialog/add-element-dialog.component';
+
+@Component({
+ selector: 'ple-messaging-message-element-interface-sub-element-table',
+ templateUrl: './sub-element-table.component.html',
+ styleUrls: ['./sub-element-table.component.sass']
+})
+export class SubElementTableComponent implements OnInit, OnChanges {
+ @Input() data: any = {};
+ @Input() dataSource: MatTableDataSource<any> = new MatTableDataSource<any>();
+ @Input() filter: string = "";
+
+ @Input() element: any = {};
+ @Output() expandRow = new EventEmitter();
+ @Input() subMessageHeaders: string[] = [];
+ private _branchId: string = "";
+ private _branchType: string = "";
+ @Input() editMode: boolean = false;
+ menuPosition = {
+ x: '0',
+ y:'0'
+ }
+ @ViewChild(MatMenuTrigger, { static: true })
+ matMenuTrigger!: MatMenuTrigger;
+ constructor(private route: ActivatedRoute, private router: Router, public dialog: MatDialog, private structureService: CurrentStateService) {
+ this.subMessageHeaders = ["name", "beginWord", "endWord", "BeginByte", "EndByte", "interfaceElementAlterable", "description", "notes"];
+ this.dataSource.data = this.data;
+ }
+ ngOnChanges(changes: SimpleChanges): void {
+ this.dataSource.data = this.data;
+ if (this.filter !== "") {
+ this.dataSource.filter = this.filter.replace('element: ', '');
+ this.filter = this.filter.replace('element: ', "");
+ if (this.dataSource.filteredData.length > 0) {
+ this.expandRow.emit(this.element);
+ }
+ }
+ }
+
+ ngOnInit(): void {
+ this.dataSource.data = this.data;
+ if (this.filter !== "") {
+ this.dataSource.filter = this.filter.replace('element: ','');
+ }
+
+ this.route.paramMap.subscribe((values) => {
+ this._branchId = values.get("branchId") || '';
+ this._branchType = values.get("branchType") || '';
+ })
+ }
+
+ valueTracker(index: any, item: any) {
+ return index;
+ }
+
+ navigateTo(location: string) {
+ this.router.navigate([this._branchType,this._branchId,"types",location], {
+ relativeTo: this.route.parent?.parent,
+ queryParamsHandling: 'merge',
+ });
+ }
+
+ openMenu(event: MouseEvent,location: string) {
+ event.preventDefault();
+ this.menuPosition.x = event.clientX + 'px';
+ this.menuPosition.y = event.clientY + 'px';
+ this.matMenuTrigger.menuData = {
+ location:location
+ }
+ this.matMenuTrigger.openMenu();
+ }
+ navigateToInNewTab(location: string) {
+ const url = this.router.serializeUrl(this.router.createUrlTree([this._branchType,this._branchId,"types", location], {
+ relativeTo: this.route.parent?.parent,
+ queryParamsHandling: 'merge',
+ }))
+ window.open(url, "_blank");
+ }
+
+ openAddElementDialog() {
+ let dialogData: AddElementDialog = {
+ id: this.element?.id||'',
+ name: this.element?.name||'',
+ element: {
+ id: '-1',
+ name: '',
+ description: '',
+ notes: '',
+ interfaceElementAlterable: true,
+ interfaceElementIndexEnd: 0,
+ interfaceElementIndexStart: 0,
+ },
+ type:{id:'',name:''}
+ }
+ let dialogRef = this.dialog.open(AddElementDialogComponent, {
+ data:dialogData
+ });
+ let createElement = dialogRef.afterClosed().pipe(
+ filter((val) => (val !== undefined ||val!==null) && val?.element!==undefined),
+ switchMap((value:AddElementDialog) =>
+ iif(() => value.element.id !== '-1' && value.element.id.length > 0 && value.type.id!==''&&value.type.name!=='',
+ this.structureService.relateElement(this.element.id, value.element.id),
+ this.structureService.createNewElement(value.element, this.element.id,value.type.id))
+ ),
+ take(1)
+ );
+ createElement.subscribe();
+ }
+
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface-routing.module.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface-routing.module.ts
new file mode 100644
index 0000000..3f9b3f7
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface-routing.module.ts
@@ -0,0 +1,11 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { MessageElementInterfaceComponent } from './message-element-interface.component';
+
+const routes: Routes = [{ path: '', component: MessageElementInterfaceComponent }];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule]
+})
+export class MessageElementInterfaceRoutingModule { }
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface.component.html
new file mode 100644
index 0000000..3b759d2
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface.component.html
@@ -0,0 +1,69 @@
+<div class="message-element-interface message-element-interface-button-header">
+ <button mat-raised-button (click)="openSettingsDialog()" style="float:right">Settings</button>
+</div>
+<ng-container *ngIf="editMode===true;">
+ <button mat-fab color="primary" (click)="openAddStructureDialog()"class="new-structure-button">+</button>
+</ng-container>
+<div class="message-element-interface message-element-interface-top-level-table">
+ <mat-form-field class="message-element-interface-table-view-width-100 message-element-interface-table-filter-padding">
+ <mat-label>Filter Message Information</mat-label>
+ <input matInput type="text" (keyup)="applyFilter($event)" #input>
+ <mat-hint>Enter text to filter Structure Table.
+ Only full text matches will show results.
+ </mat-hint>
+ </mat-form-field>
+ <table mat-table [dataSource]="dataSource" multiTemplateDataRows class="mat-elevation-z8">
+ <ng-container matColumnDef="Breadcrumbs">
+ <th mat-header-cell *matHeaderCellDef [attr.colspan]="allowedStructureHeaders.length" class="message-element-interface-table-view-message-header message-element-interface-breadcrumbs">
+ {{breadCrumb}}
+ </th>
+ </ng-container>
+ <ng-container [matColumnDef]="header" *ngFor="let header of allowedStructureHeaders; let i = index; trackBy:valueTracker;">
+ <th mat-header-cell *matHeaderCellDef [attr.colspan]="allowedStructureHeaders[i]" class="message-element-interface-table-view-message-header" [matTooltip]="header">
+ <ng-container>
+ {{header |convertMessageInterfaceTitlesToString}}
+ </ng-container>
+ </th>
+ <td mat-cell *matCellDef="let element; let i = dataIndex" [ngClass]="i%2===0? 'message-table-row-even':'message-table-row-odd'">
+ <div class="flex-row">
+ <ng-container *ngIf="editMode===true; else no_edit">
+ <ng-container *ngIf="header==='name'">
+ <button mat-icon-button [@expandButton]="!expandedElement.includes(element.id) ? 'closed' : 'open'" (click)="rowChange(element.id,!expandedElement.includes(element.id))">V</button>
+ </ng-container>
+ <osee-messaging-edit-structure-field [structureId]="element['id']" [header]="header" [value]="element[header]"></osee-messaging-edit-structure-field>
+ </ng-container>
+ <ng-template #no_edit>
+ <ng-container *ngIf="header==='name'">
+ <button mat-icon-button [@expandButton]="!expandedElement.includes(element.id) ? 'closed' : 'open'" (click)="rowChange(element.id,!expandedElement.includes(element.id))">V</button>
+ </ng-container>
+ <div *ngIf="header==='description'" [matTooltip]="element[header]" [matTooltipDisabled]="element[header].length<15" appHighlightFilteredText [searchTerms]="searchTerms" [text]="element[header] | displayTruncatedStringWithFieldOverflow:15" classToApply="ple-message-element-interface-table-highlighted-text">
+ {{element[header] | displayTruncatedStringWithFieldOverflow:15}}
+ </div>
+ <div *ngIf="header!=='description'" appHighlightFilteredText [searchTerms]="searchTerms" [text]="element[header]" classToApply="ple-message-element-interface-table-highlighted-text">
+ {{element[header]}}
+ </div>
+ </ng-template>
+ </div>
+ </td>
+ </ng-container>
+ <ng-container matColumnDef="expandedMessage">
+ <td mat-cell *matCellDef="let element" [attr.colspan]="allowedStructureHeaders.length" class="no-pad">
+ <div class="sub-message-detail message-element-interface-table-view-width-100"
+ [@detailExpand]="expandedElement.includes(element.id) ? 'expanded' : 'collapsed'">
+ <ng-container *ngIf="expandedElement.includes(element.id)">
+ <ple-messaging-message-element-interface-sub-element-table [data]="element.elements" [filter]="filter" [element]="element" (expandRow)="expandRow($event)" [subMessageHeaders]="allowedElementHeaders" [editMode]="editMode"></ple-messaging-message-element-interface-sub-element-table>
+ </ng-container>
+ </div>
+ </td>
+ </ng-container>
+ <tr mat-header-row *matHeaderRowDef="['Breadcrumbs']; sticky:true"></tr>
+ <tr mat-header-row *matHeaderRowDef="allowedStructureHeaders; sticky:true">
+ </tr>
+ <tr mat-row *matRowDef= "let row; columns: allowedStructureHeaders;"
+ class="message-detail-row"
+ [class.message-expanded-detail-row]="expandedElement.includes(row.id)">
+ </tr>
+ <tr mat-row *matRowDef="let row; columns: ['expandedMessage']" class="message-expanded-detail-row">
+ </tr>
+ </table>
+</div>
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface.component.sass
new file mode 100644
index 0000000..3d1e9c4
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface.component.sass
@@ -0,0 +1,86 @@
+table
+ width: 100%
+
+
+tr.message-expanded-detail-row
+ height: 0
+
+
+.message-detail-row td
+ border-bottom-width: 0
+
+
+.sub-message-detail
+ overflow: hidden
+ display: flex
+ flex-direction: column
+
+.message-element-interface-table-view-width-100
+ width: 100%
+
+.message-element-interface-table-view-row-display
+ display: flex
+ flex-direction: row
+ // justify-content: space-between
+
+.message-element-interface-table-view-message-header
+ font:
+ weight: bold
+
+.message-element-interface-table-view-element
+ // min-width: 4%
+ // width: 10%
+ // max-width: 8%
+ // vertical-align: middle
+ // display: flex
+ // flex-direction: column
+ // justify:
+ // content: space-around
+ // border-bottom: 1px solid
+
+.message-element-interface-table-sub-message-element
+ display: flex
+ flex-direction: row
+ justify:
+ content: space-around
+ width: 100%
+
+.no-pad:first-of-type
+ padding-left: 4%
+
+.message-element-interface-table-filter-padding
+ padding:
+ left: 1%
+ bottom: 1%
+
+.mat-hint
+ font:
+ size: 1.2em
+
+.message-element-interface-table-view-sub-message-header
+ font:
+ weight: 500
+ // size: 12px
+ text:
+ align: center
+
+.message-element-interface-breadcrumbs
+ text-align: center
+
+.message-element-interface-table-center
+ @extend .message-element-interface-breadcrumbs
+ // text:
+ // align: center
+.mat-header-cell
+ font:
+ size: 14px
+.flex-row
+ display: flex
+ flex:
+ direction: row
+
+.new-structure-button
+ z-index: 10
+ position: fixed
+ bottom: 3%
+ right: 2%
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface.component.spec.ts
new file mode 100644
index 0000000..f5a4696
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface.component.spec.ts
@@ -0,0 +1,179 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { HarnessLoader } from '@angular/cdk/testing';
+import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
+import { MatFormFieldHarness } from '@angular/material/form-field/testing';
+import { MatInputHarness } from '@angular/material/input/testing';
+import { FormsModule } from '@angular/forms';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatSelectModule } from '@angular/material/select';
+import { MatTableModule } from '@angular/material/table';
+import { MatTooltipModule } from '@angular/material/tooltip';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { Router, ActivatedRoute, convertToParamMap } from '@angular/router';
+import { BehaviorSubject, of } from 'rxjs';
+import { OseeStringUtilsDirectivesModule } from 'src/app/osee-utils/osee-string-utils/osee-string-utils-directives/osee-string-utils-directives.module';
+import { OseeStringUtilsPipesModule } from 'src/app/osee-utils/osee-string-utils/osee-string-utils-pipes/osee-string-utils-pipes.module';
+import { SubElementTableComponent } from './components/sub-element-table/sub-element-table.component';
+
+import { MessageElementInterfaceComponent } from './message-element-interface.component';
+import { ConvertMessageInterfaceTitlesToStringPipe } from '../shared/pipes/convert-message-interface-titles-to-string.pipe';
+import { MatDialogModule } from '@angular/material/dialog';
+import { CurrentStateService } from './services/current-state.service';
+import { SharedMessagingModule } from '../shared/shared-messaging.module';
+import { EditElementFieldComponent } from './components/sub-element-table/edit-element-field/edit-element-field.component';
+import { EditStructureFieldComponent } from './components/edit-structure-field/edit-structure-field.component';
+
+let loader: HarnessLoader;
+
+describe('MessageElementInterfaceComponent', () => {
+ let component: MessageElementInterfaceComponent;
+ let fixture: ComponentFixture<MessageElementInterfaceComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [
+ MatFormFieldModule,
+ MatDialogModule,
+ MatInputModule,
+ MatSelectModule,
+ FormsModule,
+ NoopAnimationsModule,
+ MatTableModule,
+ MatTooltipModule,
+ OseeStringUtilsPipesModule,
+ OseeStringUtilsDirectivesModule,
+ SharedMessagingModule
+ ],
+ declarations: [
+ MessageElementInterfaceComponent,
+ SubElementTableComponent,
+ ConvertMessageInterfaceTitlesToStringPipe,
+ EditElementFieldComponent,
+ EditStructureFieldComponent
+ ],
+ providers: [
+ { provide: Router, useValue: { navigate: () => {} } },
+ {
+ provide: ActivatedRoute,
+ useValue: {
+ paramMap: of(
+ convertToParamMap({
+ name: 'Name > Name',
+ })
+ ),
+ },
+ },
+ {
+ provide: CurrentStateService, useValue: {
+ structures: of([{
+ id: '0',
+ name: 'name',
+ elements: [{
+ id: '1',
+ name: 'name2',
+ description: 'description2',
+ notes: 'notes',
+ interfaceElementIndexEnd: 1,
+ interfaceElementIndexStart: 0,
+ interfaceElementAlterable: true,
+ platformTypeName: 'boolean',
+ platformTypeId:9
+ }],
+ description: 'description',
+ interfaceMaxSimultaneity: '0',
+ interfaceMinSimultaneity: '1',
+ interfaceTaskFileType: 1,
+ interfaceStructureCategory: 'Category 1'
+ }]),
+ BranchId:new BehaviorSubject("10")
+ }
+ },
+ ],
+ }).compileComponents();
+ });
+
+ beforeEach(() => {
+ localStorage.setItem(
+ '10',
+ JSON.stringify({
+ mim: {
+ editMode: true,
+ StructureHeaders: ["1"],
+ ElementHeaders: ["2"],
+ }
+ }
+ )
+ );
+ fixture = TestBed.createComponent(MessageElementInterfaceComponent);
+ component = fixture.componentInstance;
+ loader = TestbedHarnessEnvironment.loader(fixture);
+ fixture.detectChanges();
+ });
+
+ beforeEach(function () {
+ var store:any = {};
+
+ spyOn(localStorage, 'getItem').and.callFake(function (key) {
+ return store[key];
+ });
+ spyOn(localStorage, 'setItem').and.callFake(function (key, value) {
+ return store[key] = value + '';
+ });
+ spyOn(localStorage, 'clear').and.callFake(function () {
+ store = {};
+ });
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should remove element from expandedElement', () => {
+ //@todo: Refactor once types come in
+ component.expandedElement = [1, 2, 3, 4, 5, 7];
+ component.hideRow(4);
+ expect(!component.expandedElement.includes(4)).toBeTruthy();
+ });
+
+ it('should add element from expandedElement', () => {
+ //@todo: Refactor once types come in
+ component.expandedElement = [1, 2, 3, 4, 5, 7];
+ component.expandRow(9);
+ expect(component.expandedElement.includes(9)).toBeTruthy();
+ });
+
+ it('should find a truncatedElement', () => {
+ //@todo: Refactor once types come in
+ component.truncatedSections = ['hello', 'world'];
+ let result = component.isTruncated('world');
+ expect(result).toBeTruthy();
+ });
+
+ it('should not find a truncatedElement', () => {
+ //@todo: Refactor once types come in
+ component.truncatedSections = ['hello', 'world'];
+ let result = component.isTruncated('abcdef');
+ expect(result).toBeFalsy();
+ });
+
+ it('should filter text', async () => {
+ //@todo: Refactor once types come in
+ const form = await loader.getHarness(MatFormFieldHarness);
+ const control = await form.getControl(MatInputHarness);
+ await control?.setValue('CCS Audio File');
+ expect(
+ fixture.componentInstance.dataSource.filter ===
+ 'CCS Audio File'.trim().toLowerCase()
+ ).toBeTruthy();
+ });
+
+ // it('should filter sub-element text',async () => {
+ // //@todo: Refactor once types come in
+ //throws error?
+ // const form = await loader.getHarness(MatFormFieldHarness);
+ // const control = await form.getControl(MatInputHarness);
+ // await control?.setValue("element: Audio File ID");
+ // expect(component.filter==="element: Audio File ID".trim().toLowerCase()).toBeTruthy();
+ // });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface.component.ts
new file mode 100644
index 0000000..ff17dbf
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface.component.ts
@@ -0,0 +1,241 @@
+import {
+ trigger,
+ state,
+ style,
+ transition,
+ animate,
+} from '@angular/animations';
+import { Component, OnInit } from '@angular/core';
+import { MatDialog } from '@angular/material/dialog';
+import { MatTableDataSource } from '@angular/material/table';
+import { ActivatedRoute, Router } from '@angular/router';
+import { ColumnPreferencesDialogComponent } from '../shared/components/dialogs/column-preferences-dialog/column-preferences-dialog.component';
+import { CurrentStateService } from './services/current-state.service';
+import { settingsDialogData } from '../shared/types/settingsdialog';
+import { structure } from './types/structure';
+import { branchStorage } from '../shared/types/branchstorage';
+import { fromEvent, iif } from 'rxjs';
+import { AddStructureDialogComponent } from './components/add-structure-dialog/add-structure-dialog.component';
+import { AddStructureDialog } from './types/AddStructureDialog';
+import { filter, first, switchMap } from 'rxjs/operators';
+
+@Component({
+ selector: 'ple-messaging-message-element-interface',
+ templateUrl: './message-element-interface.component.html',
+ styleUrls: ['./message-element-interface.component.sass'],
+ animations: [
+ trigger('detailExpand', [
+ state('collapsed', style({ height: '0px', minHeight: '0' })),
+ state('expanded', style({ height: '60vh', overflowY: 'auto' })),
+ transition(
+ 'expanded <=> collapsed',
+ animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')
+ ),
+ ]),
+ trigger('expandButton', [
+ state('closed', style({ transform: 'rotate(0)' })),
+ state('open', style({ transform: 'rotate(-180deg)' })),
+ transition('open => closed', animate('250ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
+ transition('closed => open', animate('250ms cubic-bezier(0.4, 0.0, 0.2, 1)'))
+ ])
+ ],
+})
+export class MessageElementInterfaceComponent implements OnInit {
+ messageData = this.structureService.structures;
+ dataSource: MatTableDataSource<structure> =
+ new MatTableDataSource<structure>();
+ headers: string[] = [];
+ truncatedSections: string[] = [];
+ allowedStructureHeaders: string[] = [];
+ allStructureHeaders: string[] = [
+ 'name',
+ 'description',
+ 'interfaceMaxSimultaneity',
+ 'interfaceMinSimultaneity',
+ 'interfaceTaskFileType',
+ 'interfaceStructureCategory',
+ 'AttributeCount',
+ 'SizeInBytes',
+ 'BytesPerSecondMinimum',
+ 'BytesPerSecondMaximum',
+ 'GenerationIndicator',
+ ];
+
+ allowedElementHeaders: string[] = [
+ 'name',
+ 'platformTypeName2',
+ 'interfaceElementAlterable',
+ 'description',
+ 'notes',
+ ];
+ allElementHeaders: string[] = [
+ 'name',
+ 'platformTypeName2',
+ 'beginWord',
+ 'endWord',
+ 'BeginByte',
+ 'EndByte',
+ 'interfaceElementAlterable',
+ 'description',
+ 'notes',
+ ];
+ expandedElement: Array<any> = [];
+ filter: string = '';
+ searchTerms: string = '';
+ breadCrumb: string = '';
+ editMode: boolean = false;
+ constructor(
+ private route: ActivatedRoute,
+ private router: Router,
+ public dialog: MatDialog,
+ private structureService: CurrentStateService
+ ) {
+ this.messageData.subscribe((value) => {
+ this.dataSource.data = value;
+ });
+ this.allowedStructureHeaders = [
+ 'name',
+ 'description',
+ 'interfaceMaxSimultaneity',
+ 'interfaceMinSimultaneity',
+ 'interfaceTaskFileType',
+ 'interfaceStructureCategory',
+ ]; //, "TaskFileType"
+ this.truncatedSections = ['description', 'EnumsLiteralsDesc', 'Notes'];
+ //this.hiddenHeaders=["expandoButton"]
+ }
+
+ ngOnInit(): void {
+ this.route.paramMap.subscribe((values) => {
+ this.breadCrumb = values.get('name') || '';
+ this.structureService.branchId = values.get('branchId') || '';
+ this.structureService.messageId = values.get('messageId') || '';
+ this.structureService.subMessageId = values.get('subMessageId') || '';
+ });
+ //@todo: remove when user preferences are available on backend
+ let branchStorage = JSON.parse(
+ localStorage.getItem(this.structureService.BranchId.getValue()) || '{}'
+ ) as branchStorage;
+ if (branchStorage?.mim?.editMode) {
+ this.editMode = branchStorage.mim.editMode;
+ }
+ if (branchStorage?.mim?.StructureHeaders?.length > 0) {
+ this.allowedStructureHeaders = branchStorage.mim.StructureHeaders;
+ }
+ if (branchStorage?.mim?.ElementHeaders?.length > 0) {
+ this.allowedElementHeaders = branchStorage.mim.ElementHeaders;
+ }
+ }
+
+ valueTracker(index: any, item: any) {
+ return index;
+ }
+
+ expandRow(value: any) {
+ if (this.expandedElement.indexOf(value) === -1) {
+ this.expandedElement.push(value);
+ }
+ }
+ hideRow(value: any) {
+ let index = this.expandedElement.indexOf(value);
+ if (index > -1) {
+ this.expandedElement.splice(index, 1);
+ }
+ }
+
+ rowChange(value: any, type: boolean) {
+ if (type) {
+ this.expandRow(value);
+ } else {
+ this.hideRow(value);
+ }
+ }
+
+ applyFilter(event: Event) {
+ const filterValue = (event.target as HTMLInputElement).value;
+ this.searchTerms = filterValue;
+ if (filterValue.includes('element: ')) {
+ this.filter = filterValue.trim().toLowerCase();
+ this.dataSource.filter = '';
+ } else {
+ this.dataSource.filter = filterValue.trim().toLowerCase();
+ }
+ }
+ isTruncated(value: string) {
+ if (this.truncatedSections.find((x) => x === value)) {
+ return true;
+ }
+ return false;
+ }
+
+ openSettingsDialog() {
+ let dialogData: settingsDialogData = {
+ branchId: this.structureService.BranchId.getValue(),
+ allHeaders2: this.allElementHeaders,
+ allowedHeaders2: this.allowedElementHeaders,
+ allHeaders1: this.allStructureHeaders,
+ allowedHeaders1: this.allowedStructureHeaders,
+ editable: this.editMode,
+ headers1Label: 'Structure Headers',
+ headers2Label: 'Element Headers',
+ headersTableActive: true,
+ };
+ const dialogRef = this.dialog.open(ColumnPreferencesDialogComponent, {
+ data: dialogData,
+ });
+ dialogRef.afterClosed().subscribe((result: settingsDialogData) => {
+ this.allowedElementHeaders = result.allowedHeaders2;
+ this.allowedStructureHeaders = result.allowedHeaders1;
+ this.editMode = result.editable;
+ //@todo: remove when user preferences are available on backend
+ if (localStorage.getItem(this.structureService.BranchId.getValue())) {
+ let branchStorage = JSON.parse(
+ localStorage.getItem(this.structureService.BranchId.getValue()) ||
+ '{}'
+ ) as branchStorage;
+ branchStorage.mim['editMode'] = result.editable;
+ branchStorage.mim['StructureHeaders'] = result.allowedHeaders1;
+ branchStorage.mim['ElementHeaders'] = result.allowedHeaders2;
+ localStorage.setItem(
+ this.structureService.BranchId.getValue(),
+ JSON.stringify(branchStorage)
+ );
+ } else {
+ localStorage.setItem(
+ this.structureService.BranchId.getValue(),
+ JSON.stringify({
+ mim: {
+ editMode: result.editable,
+ StructureHeaders: result.allowedHeaders1,
+ ElementHeaders: result.allowedHeaders2,
+ },
+ })
+ );
+ }
+ });
+ }
+ openAddStructureDialog() {
+ let dialogData:AddStructureDialog= {
+ id: this.structureService.subMessageId,
+ name: this.breadCrumb,
+ structure: {
+ id: '-1',
+ name: '',
+ elements: [],
+ description: '',
+ interfaceMaxSimultaneity: '',
+ interfaceMinSimultaneity: '',
+ interfaceStructureCategory: '',
+ interfaceTaskFileType:0
+ }
+ }
+ let dialogRef=this.dialog.open(AddStructureDialogComponent, {
+ data:dialogData
+ });
+ dialogRef.afterClosed().pipe(
+ filter((val) => val !== undefined),
+ switchMap((value: AddStructureDialog) => iif(() => value.structure.id !== '-1' && value.structure.id.length > 0, this.structureService.relateStructure(value.structure.id), this.structureService.createStructure(value.structure))),
+ first()
+ ).subscribe(() => { },()=>{});
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface.module.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface.module.ts
new file mode 100644
index 0000000..c204fc5
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/message-element-interface.module.ts
@@ -0,0 +1,53 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { MatTableModule } from '@angular/material/table';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatTooltipModule } from '@angular/material/tooltip';
+import {MatListModule} from '@angular/material/list';
+
+import { MessageElementInterfaceRoutingModule } from './message-element-interface-routing.module';
+import { MessageElementInterfaceComponent } from './message-element-interface.component';
+import { PleSharedMaterialModule } from '../../ple-shared-material/ple-shared-material.module';
+import { OseeStringUtilsPipesModule } from '../../../osee-utils/osee-string-utils/osee-string-utils-pipes/osee-string-utils-pipes.module';
+import { SubElementTableComponent } from './components/sub-element-table/sub-element-table.component';
+import { OseeStringUtilsDirectivesModule } from 'src/app/osee-utils/osee-string-utils/osee-string-utils-directives/osee-string-utils-directives.module';
+import { MatDialogModule } from '@angular/material/dialog';
+import { FormsModule } from '@angular/forms';
+import { SharedMessagingModule } from '../shared/shared-messaging.module';
+import { EditStructureFieldComponent } from './components/edit-structure-field/edit-structure-field.component';
+import { AddStructureDialogComponent } from './components/add-structure-dialog/add-structure-dialog.component';
+import { MatSelectModule } from '@angular/material/select';
+import { MatStepperModule } from '@angular/material/stepper';
+import { AddElementDialogComponent } from './components/add-element-dialog/add-element-dialog.component';
+import { EditElementFieldComponent } from './components/sub-element-table/edit-element-field/edit-element-field.component';
+import { MatSlideToggleModule } from '@angular/material/slide-toggle';
+import { MatMenuModule } from '@angular/material/menu';
+import {MatAutocompleteModule} from '@angular/material/autocomplete';
+
+
+@NgModule({
+ declarations: [MessageElementInterfaceComponent, SubElementTableComponent, EditStructureFieldComponent, AddStructureDialogComponent, AddElementDialogComponent, EditElementFieldComponent],
+ imports: [
+ CommonModule,
+ MatTableModule,
+ MatFormFieldModule,
+ MatSelectModule,
+ MatInputModule,
+ MatTooltipModule,
+ MatStepperModule,
+ MatDialogModule,
+ MatMenuModule,
+ MatListModule,
+ MatSlideToggleModule,
+ FormsModule,
+ MatAutocompleteModule,
+ PleSharedMaterialModule,
+ OseeStringUtilsPipesModule,
+ OseeStringUtilsDirectivesModule,
+ MessageElementInterfaceRoutingModule,
+ SharedMessagingModule
+ ]
+})
+export class MessageElementInterfaceModule { }
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/current-state.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/current-state.service.spec.ts
new file mode 100644
index 0000000..bba81c0
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/current-state.service.spec.ts
@@ -0,0 +1,50 @@
+import { HttpClient } from '@angular/common/http';
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { apiURL } from 'src/environments/environment';
+import { structure } from '../types/structure';
+
+import { CurrentStateService } from './current-state.service';
+
+describe('CurrentStateService', () => {
+ let service: CurrentStateService;
+ let httpClient: HttpClient;
+ let httpTestingController: HttpTestingController;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports:[HttpClientTestingModule]
+ });
+ service = TestBed.inject(CurrentStateService);
+ httpClient = TestBed.inject(HttpClient);
+ httpTestingController = TestBed.inject(HttpTestingController);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should get filtered structures', fakeAsync(() => {
+ let testData: structure[] = [{
+ id: '0',
+ name: 'name',
+ elements: [],
+ description: 'description',
+ interfaceMaxSimultaneity: '1',
+ interfaceMinSimultaneity: '0',
+ interfaceStructureCategory: '1',
+ interfaceTaskFileType:1
+ }]
+
+ service.structures.subscribe();
+ service.branchId = "0";
+ service.filter = "0";
+ service.messageId = "1";
+ service.subMessageId = "2";
+ tick(500);
+ const req = httpTestingController.expectOne(apiURL + "/mim/branch/" + 0 + "/messages/" + 1 + "/submessages/" + 2 + "/structures/filter/" + 0);
+ expect(req.request.method).toEqual('GET');
+ req.flush(testData);
+ httpTestingController.verify();
+ }));
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/current-state.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/current-state.service.ts
new file mode 100644
index 0000000..7111530
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/current-state.service.ts
@@ -0,0 +1,160 @@
+import { Injectable } from '@angular/core';
+import { combineLatest, from, Observable, of } from 'rxjs';
+import { share, debounceTime, distinctUntilChanged, switchMap, repeatWhen, mergeMap, scan, distinct, tap, shareReplay, first } from 'rxjs/operators';
+import { element } from '../types/element';
+import { structure } from '../types/structure';
+import { ElementService } from './element.service';
+import { MessagesService } from './messages.service';
+import { PlatformTypeService } from './platform-type.service';
+import { StructuresService } from './structures.service';
+import { UiService } from './ui.service';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class CurrentStateService {
+
+ private _structures = combineLatest(this.ui.filter, this.ui.BranchId, this.ui.messageId, this.ui.subMessageId).pipe(
+ share(),
+ debounceTime(500),
+ distinctUntilChanged(),
+ switchMap(x => this.structure.getFilteredStructures(...x).pipe(
+ repeatWhen(_ => this.ui.UpdateRequired),
+ share(),
+ shareReplay(1),
+ )),
+ shareReplay(1),
+ )
+
+ //private _types = this.typeService.getTypes(this.BranchId.getValue());
+ private _types = this.ui.BranchId.pipe(
+ share(),
+ switchMap(x => this.typeService.getTypes(x).pipe(
+ repeatWhen(_ => this.ui.UpdateRequired),
+ share(),
+ shareReplay(1),
+ )),
+ shareReplay(1),
+ )
+
+ constructor (private ui: UiService, private structure: StructuresService, private messages:MessagesService, private elements:ElementService, private typeService: PlatformTypeService) { }
+
+ get structures() {
+ return this._structures;
+ }
+
+ set filter(value: string) {
+ this.ui.filterString = value;
+ }
+
+ set branchId(value: string) {
+ this.ui.BranchIdString = value;
+ }
+
+ get BranchId() {
+ return this.ui.BranchId;
+ }
+
+ set messageId(value: string) {
+ this.ui.messageIdString = value;
+ }
+
+ get MessageId() {
+ return this.ui.messageId;
+ }
+
+ get SubMessageId() {
+ return this.ui.subMessageId
+ }
+
+ set subMessageId(value: string) {
+ this.ui.subMessageIdString = value;
+ }
+
+ private get structureObservable(){
+ return this.messages.getMessages(this.BranchId.getValue()).pipe(
+ mergeMap(messages => from(messages).pipe(
+ mergeMap(message => of(message?.subMessages).pipe(
+ mergeMap(submessage => from(submessage).pipe(
+ distinct((x) => { return x.id }),
+ mergeMap((submessage) => this.structure.getFilteredStructures("", this.BranchId.getValue(), message?.id, submessage?.id).pipe(
+ mergeMap(structures => from(structures).pipe(
+ distinct((structure)=>{return structure.id})
+ ))
+ )),
+ )),
+ )),
+ )),
+ )
+ }
+ get availableStructures(): Observable<structure[]> {
+ return this.structureObservable.pipe(
+ scan((acc, curr) => [...acc, curr], [] as structure[]),
+ )
+ }
+
+ get availableElements(): Observable<element[]>{
+ return this.structureObservable.pipe(
+ mergeMap((value) => from(value.elements).pipe(
+ distinct()
+ )),
+ scan((acc, curr) => [...acc, curr], [] as element[]),
+ )
+ }
+
+ get types() {
+ return this._types;
+ }
+
+ createStructure(body:Partial<structure>) {
+ return this.structure.createStructure(body, this.BranchId.getValue(), this.MessageId.getValue(), this.SubMessageId.getValue()).pipe(
+ tap(() => {
+ this.ui.updateMessages = true;
+ })
+ );
+ }
+
+ relateStructure(structureId:string) {
+ return this.structure.relateStructure(this.BranchId.getValue(), this.MessageId.getValue(), this.SubMessageId.getValue(), structureId).pipe(
+ tap(() => {
+ this.ui.updateMessages = true;
+ })
+ );
+ }
+ partialUpdateStructure(body:Partial<structure>) {
+ return this.structure.partialUpdateStructure(body, this.BranchId.getValue(), this.MessageId.getValue(), this.SubMessageId.getValue()).pipe(
+ tap(() => {
+ this.ui.updateMessages = true;
+ })
+ );
+ }
+
+ partialUpdateElement(body: Partial<element>, structureId: string) {
+ return this.elements.partialUpdateElement(body, this.BranchId.getValue(), this.MessageId.getValue(), this.SubMessageId.getValue(), structureId).pipe(
+ tap(() => {
+ this.ui.updateMessages = true;
+ })
+ )
+ }
+
+ createNewElement(body: Partial<element>, structureId:string, typeId: string) {
+ return this.elements.createNewElement(body, this.BranchId.getValue(), this.MessageId.getValue(), this.SubMessageId.getValue(), structureId).pipe(
+ switchMap((val) => this.changeElementPlatformType(structureId, val.ids[0], typeId)),
+ first()
+ )
+ }
+ relateElement(structureId: string, elementId: string) {
+ return this.elements.relateElement(this.BranchId.getValue(), this.MessageId.getValue(), this.SubMessageId.getValue(), structureId,elementId).pipe(
+ tap(() => {
+ this.ui.updateMessages = true;
+ })
+ )
+ }
+ changeElementPlatformType(structureId:string,elementId:string,typeId:string) {
+ return this.elements.relateElementToPlatformType(this.BranchId.getValue(), this.MessageId.getValue(), this.SubMessageId.getValue(), structureId, elementId, typeId).pipe(
+ tap(() => {
+ this.ui.updateMessages = true;
+ })
+ )
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/element.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/element.service.spec.ts
new file mode 100644
index 0000000..a5ce659
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/element.service.spec.ts
@@ -0,0 +1,19 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { ElementService } from './element.service';
+
+describe('ElementService', () => {
+ let service: ElementService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports:[HttpClientTestingModule]
+ });
+ service = TestBed.inject(ElementService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/element.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/element.service.ts
new file mode 100644
index 0000000..b2b6edf
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/element.service.ts
@@ -0,0 +1,29 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs';
+import { apiURL } from 'src/environments/environment';
+import { StructureApiResponse } from '../types/ApiResponse';
+import { element } from '../types/element';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class ElementService {
+
+ constructor (private http: HttpClient) { }
+
+ partialUpdateElement(body: Partial<element>, branchId: string, messageId: string,subMessageId: string, structureId:string):Observable<StructureApiResponse> {
+ return this.http.patch<StructureApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/"+ subMessageId+"/structures/"+structureId+"/elements", body);
+ }
+
+ createNewElement(body: Partial<element>, branchId: string, messageId: string,subMessageId: string, structureId:string):Observable<StructureApiResponse> {
+ return this.http.post<StructureApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/"+ subMessageId+"/structures/"+structureId+"/elements", body);
+ }
+ relateElement(branchId: string,messageId: string, subMessageId: string, structureId: string, elementId: string) {
+ return this.http.patch<StructureApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/"+ subMessageId+"/structures/"+structureId+"/elements/"+elementId, null);
+ }
+
+ relateElementToPlatformType(branchId: string, messageId: string,subMessageId: string, structureId:string,elementId:string, typeId:string):Observable<StructureApiResponse> {
+ return this.http.patch<StructureApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/"+ subMessageId+"/structures/"+structureId+"/elements/"+elementId+"/setType/"+typeId, null);
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/messages.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/messages.service.spec.ts
new file mode 100644
index 0000000..063b10e
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/messages.service.spec.ts
@@ -0,0 +1,19 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { MessagesService } from './messages.service';
+
+describe('MessagesService', () => {
+ let service: MessagesService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports:[HttpClientTestingModule]
+ });
+ service = TestBed.inject(MessagesService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/messages.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/messages.service.ts
new file mode 100644
index 0000000..eabb057
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/messages.service.ts
@@ -0,0 +1,22 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs';
+import { apiURL } from 'src/environments/environment';
+import { message } from '../../message-interface/types/messages';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class MessagesService {
+
+ constructor (private http: HttpClient) { }
+
+ /**
+ * Gets an array of messages based on a filter condition
+ * @param branchId branch to look for messages on
+ * @returns Observable of an array of messages matching filter condition
+ */
+ getMessages(branchId: string):Observable<message[]> {
+ return this.http.get<message[]>(apiURL + "/mim/branch/" + branchId + "/messages");
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/platform-type.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/platform-type.service.spec.ts
new file mode 100644
index 0000000..e2ba912
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/platform-type.service.spec.ts
@@ -0,0 +1,19 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { PlatformTypeService } from './platform-type.service';
+
+describe('PlatformTypeService', () => {
+ let service: PlatformTypeService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports:[HttpClientTestingModule]
+ });
+ service = TestBed.inject(PlatformTypeService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/platform-type.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/platform-type.service.ts
new file mode 100644
index 0000000..d39dd48
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/platform-type.service.ts
@@ -0,0 +1,22 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs';
+import { apiURL } from 'src/environments/environment';
+import { PlatformType } from '../types/platformtype';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class PlatformTypeService {
+
+ constructor (private http: HttpClient) { }
+
+ /**
+ * Gets a list of Platform Types based on a filter condition using the platform types filter GET API
+ * @param branchId @type {string} branch to fetch from
+ * @returns @type {Observable<PlatformType[]>} Observable of array of platform types matching filter conditions (see @type {PlatformType} and @type {Observable})
+ */
+ getTypes(branchId: string): Observable<PlatformType[]> {
+ return this.http.get<PlatformType[]>(apiURL + "/mim/branch/" + branchId + "/types");
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/structures.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/structures.service.spec.ts
new file mode 100644
index 0000000..46aa829
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/structures.service.spec.ts
@@ -0,0 +1,50 @@
+import { TestBed } from '@angular/core/testing';
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+
+import { StructuresService } from './structures.service';
+import { HttpClient } from '@angular/common/http';
+import { TestScheduler } from 'rxjs/testing';
+import { structure } from '../types/structure';
+import { apiURL } from 'src/environments/environment';
+
+describe('StructuresService', () => {
+ let service: StructuresService;
+ let httpClient: HttpClient;
+ let httpTestingController: HttpTestingController;
+ let scheduler: TestScheduler;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports:[HttpClientTestingModule]
+ });
+ service = TestBed.inject(StructuresService);
+ httpClient = TestBed.inject(HttpClient);
+ httpTestingController = TestBed.inject(HttpTestingController);
+ });
+
+ beforeEach(() => scheduler = new TestScheduler((actual, expected) => {
+ expect(actual).toEqual(expected);
+ }));
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should get filtered structures', () => {
+ let testData: structure[] = [{
+ id: '0',
+ name: 'name',
+ elements: [],
+ description: 'description',
+ interfaceMaxSimultaneity: '1',
+ interfaceMinSimultaneity: '0',
+ interfaceStructureCategory: '1',
+ interfaceTaskFileType:1
+ }]
+ service.getFilteredStructures('0', '0', '1', '2').subscribe();
+ const req = httpTestingController.expectOne(apiURL + "/mim/branch/" + 0 + "/messages/" + 1 + "/submessages/" + 2 + "/structures/filter/" + 0);
+ expect(req.request.method).toEqual('GET');
+ req.flush(testData);
+ httpTestingController.verify();
+ })
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/structures.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/structures.service.ts
new file mode 100644
index 0000000..0dbfbe8
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/structures.service.ts
@@ -0,0 +1,27 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs';
+import { apiURL } from 'src/environments/environment';
+import { StructureApiResponse } from '../types/ApiResponse';
+import { structure } from '../types/structure';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class StructuresService {
+
+ constructor (private http: HttpClient) { }
+
+ getFilteredStructures(filter: string, branchId: string, messageId:string,subMessageId:string): Observable<structure[]> {
+ return this.http.get<structure[]>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/" + subMessageId + "/structures/filter/" + filter);
+ }
+ createStructure(body:Partial<structure>,branchId: string,messageId: string, subMessageId: string) {
+ return this.http.post<StructureApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/" + subMessageId + "/structures", body);
+ }
+ relateStructure(branchId: string, messageId: string, subMessageId: string, structureId: string) {
+ return this.http.patch<StructureApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/" + subMessageId + "/structures/"+structureId,null);
+ }
+ partialUpdateStructure(body: Partial<structure>, branchId: string, messageId: string,subMessageId: string):Observable<StructureApiResponse> {
+ return this.http.patch<StructureApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/"+ subMessageId+"/structures", body);
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/ui.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/ui.service.spec.ts
new file mode 100644
index 0000000..cbc6bf3
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/ui.service.spec.ts
@@ -0,0 +1,69 @@
+import { TestBed } from '@angular/core/testing';
+import { count } from 'rxjs/operators';
+import {TestScheduler} from 'rxjs/testing'
+import { UiService } from './ui.service';
+
+describe('UiService', () => {
+ let service: UiService;
+ let scheduler: TestScheduler;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({});
+ service = TestBed.inject(UiService);
+ });
+
+ beforeEach(() => scheduler = new TestScheduler((actual, expected) => {
+ expect(actual).toEqual(expected);
+ }));
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should set filter value', () => {
+ scheduler.run(() => {
+ const expectedfilterValues = { a: 'a', b: 'b' };
+ const expectedMarble = 'a'
+ scheduler.expectObservable(service.filter).toBe(expectedMarble, expectedfilterValues);
+ service.filterString = "a";
+ service.filterString = "a";
+ service.filterString = "b";
+ service.filterString = "a";
+ })
+ });
+
+ it('should set branch value', () => {
+ scheduler.run(() => {
+ const expectedfilterValues = { a: '1', b: '2' };
+ const expectedMarble = 'a'
+ scheduler.expectObservable(service.BranchId).toBe(expectedMarble, expectedfilterValues);
+ service.BranchIdString='1'
+ service.BranchIdString='1'
+ service.BranchIdString='2'
+ service.BranchIdString='1'
+ })
+ });
+
+ it('should set message value', () => {
+ scheduler.run(() => {
+ const expectedfilterValues = { a: '1', b: '2' };
+ const expectedMarble = 'a'
+ scheduler.expectObservable(service.messageId).toBe(expectedMarble, expectedfilterValues);
+ service.messageIdString='1'
+ service.messageIdString='1'
+ service.messageIdString='2'
+ service.messageIdString='1'
+ })
+ });
+
+ it('should set sub message value', () => {
+ scheduler.run(() => {
+ const expectedfilterValues = { a: '1', b: '2' };
+ const expectedMarble = 'a'
+ scheduler.expectObservable(service.subMessageId).toBe(expectedMarble, expectedfilterValues);
+ service.subMessageIdString='1'
+ service.subMessageIdString='1'
+ service.subMessageIdString='2'
+ service.subMessageIdString='1'
+ })
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/ui.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/ui.service.ts
new file mode 100644
index 0000000..cb53aa1
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/services/ui.service.ts
@@ -0,0 +1,58 @@
+import { Injectable } from '@angular/core';
+import { BehaviorSubject, Subject } from 'rxjs';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class UiService {
+
+ private _filter: BehaviorSubject<string> = new BehaviorSubject<string>("");
+
+ private _UpdateRequired: Subject<boolean> = new Subject<boolean>();
+ private _branchId: BehaviorSubject<string> = new BehaviorSubject<string>("0");
+ private _messageId: BehaviorSubject<string> = new BehaviorSubject<string>("0");
+ private _subMessageId: BehaviorSubject<string> = new BehaviorSubject<string>("0");
+ constructor() { }
+
+ get filter() {
+ return this._filter
+ }
+
+ set filterString(filter: string) {
+ if (filter !== this._filter.getValue()) {
+ this._filter.next(filter);
+ }
+ }
+
+ get UpdateRequired() {
+ return this._UpdateRequired;
+ }
+
+ set updateMessages(value: boolean) {
+ this._UpdateRequired.next(value);
+ }
+
+ get BranchId() {
+ return this._branchId;
+ }
+
+ set BranchIdString(value: string) {
+ this._branchId.next(value);
+ }
+
+ get messageId() {
+ return this._messageId;
+ }
+
+ set messageIdString(value: string) {
+ this._messageId.next(value);
+ }
+
+ get subMessageId() {
+ return this._subMessageId;
+ }
+
+ set subMessageIdString(value: string) {
+ this._subMessageId.next(value);
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/types/AddElementDialog.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/types/AddElementDialog.d.ts
new file mode 100644
index 0000000..622d1bc
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/types/AddElementDialog.d.ts
@@ -0,0 +1,8 @@
+import { element } from "./element";
+
+export interface AddElementDialog{
+ id: string,
+ name: string,
+ element: element,
+ type:{id:string,name:string}
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/types/AddStructureDialog.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/types/AddStructureDialog.d.ts
new file mode 100644
index 0000000..d784097
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/types/AddStructureDialog.d.ts
@@ -0,0 +1,7 @@
+import { structure } from "./structure";
+
+export interface AddStructureDialog{
+ id: string,
+ name: string,
+ structure:structure
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/types/ApiResponse.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/types/ApiResponse.d.ts
new file mode 100644
index 0000000..63f22f1
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/types/ApiResponse.d.ts
@@ -0,0 +1,21 @@
+/**
+ * Response the Platform Types API should return when doing a POST,PUT,PATCH, or DELETE to indicate success/status of API
+ */
+ export interface StructureApiResponse {
+ empty: boolean,
+ errorCount: number,
+ errors: boolean,
+ failed: boolean,
+ ids: string[],
+ infoCount: boolean,
+ numErrors: number,
+ numErrorsViaSearch: number,
+ numWarnings: number,
+ numWarningsViaSearch: number,
+ results: string[],
+ success: boolean,
+ tables: string[],
+ title: string,
+ txId: string,
+ warningCount: number
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/types/element.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/types/element.d.ts
new file mode 100644
index 0000000..d2d6af7
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/types/element.d.ts
@@ -0,0 +1,11 @@
+export interface element {
+ id: string,
+ name: string,
+ description: string,
+ notes: string,
+ interfaceElementIndexEnd: number,
+ interfaceElementIndexStart: number,
+ interfaceElementAlterable: boolean,
+ platformTypeName2?: string,
+ platformTypeId?:number
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/types/platformtype.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/types/platformtype.d.ts
new file mode 100644
index 0000000..455d1fd
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/types/platformtype.d.ts
@@ -0,0 +1,21 @@
+/**
+ * Platform Type as defined by the API, ids are required when fetching or updating a platform type
+ */
+ export interface PlatformType {
+ id?: string,
+ interfaceLogicalType: string,
+ interfacePlatform2sComplement: boolean,
+ interfacePlatformTypeAnalogAccuracy: string | null,
+ interfacePlatformTypeBitsResolution: string | null,
+ interfacePlatformTypeBitSize: string | null,
+ interfacePlatformTypeCompRate: string | null,
+ interfacePlatformTypeDefaultValue: string | null,
+ interfacePlatformTypeEnumLiteral: string | null,
+ interfacePlatformTypeMaxval: string | null,
+ interfacePlatformTypeMinval: string | null,
+ interfacePlatformTypeMsbValue: string | null,
+ interfacePlatformTypeUnits: string | null,
+ interfacePlatformTypeValidRangeDescription: string | null,
+ name: string
+
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/types/structure.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/types/structure.d.ts
new file mode 100644
index 0000000..50bfa84
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-element-interface/types/structure.d.ts
@@ -0,0 +1,12 @@
+import { element } from "./element";
+
+export interface structure {
+ id: string,
+ name: string,
+ elements: element[],
+ description: string,
+ interfaceMaxSimultaneity: string,
+ interfaceMinSimultaneity: string,
+ interfaceTaskFileType: number,
+ interfaceStructureCategory: string
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/add-message-dialog/add-message-dialog.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/add-message-dialog/add-message-dialog.component.html
new file mode 100644
index 0000000..d1af6cf
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/add-message-dialog/add-message-dialog.component.html
@@ -0,0 +1,56 @@
+<h1 mat-dialog-title>Create New Message</h1>
+<mat-dialog-content>
+ <mat-form-field>
+ <label>Name</label>
+ <input matInput type="text" [(ngModel)]="data.name" #input required>
+ </mat-form-field>
+ <br>
+ <mat-form-field>
+ <label>Description</label>
+ <input matInput type="text" [(ngModel)]="data.description" #input required>
+ </mat-form-field>
+ <br>
+ <mat-form-field>
+ <label>Rate</label>
+ <input matInput type="text" [(ngModel)]="data.interfaceMessageRate" #input required>
+ </mat-form-field>
+ <br>
+ <mat-form-field>
+ <label>Periodicity</label>
+ <input matInput type="text" [(ngModel)]="data.interfaceMessagePeriodicity" #input required>
+ </mat-form-field>
+ <br>
+ <!-- <mat-form-field>
+ <label>Read/Write</label>
+ <input matInput type="text" [(ngModel)]="data.interfaceMessageWriteAccess" #input required>
+ </mat-form-field> -->
+ <mat-slide-toggle [(ngModel)]="data.interfaceMessageWriteAccess" labelPosition='before'>
+ Read
+ </mat-slide-toggle>
+ Write
+ <br>
+ <mat-form-field>
+ <label>Type</label>
+ <input matInput type="text" [(ngModel)]="data.interfaceMessageType" #input required>
+ </mat-form-field>
+ <br>
+ <mat-form-field>
+ <label>Message Number</label>
+ <input matInput type="text" [(ngModel)]="data.interfaceMessageNumber" #input required>
+ </mat-form-field>
+ <br>
+</mat-dialog-content>
+<mat-dialog-actions align="end">
+ <button mat-button (click)="onNoClick()">
+ Cancel
+ </button>
+ <button mat-raised-button [mat-dialog-close]="data" color="primary" [disabled]="data.name.length===0||
+ data.description.length===0||
+ data.interfaceMessageNumber.length===0||
+ data.interfaceMessagePeriodicity.length===0||
+ data.interfaceMessageType.length===0||
+ data.interfaceMessageWriteAccess.length===0||
+ data.interfaceMessageRate.length===0">
+ Ok
+ </button>
+</mat-dialog-actions>
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/add-message-dialog/add-message-dialog.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/add-message-dialog/add-message-dialog.component.sass
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/add-message-dialog/add-message-dialog.component.sass
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/add-message-dialog/add-message-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/add-message-dialog/add-message-dialog.component.spec.ts
new file mode 100644
index 0000000..1370ec0
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/add-message-dialog/add-message-dialog.component.spec.ts
@@ -0,0 +1,47 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { AddMessageDialog } from '../../../types/AddMessageDialog';
+
+import { AddMessageDialogComponent } from './add-message-dialog.component';
+
+describe('AddMessageDialogComponent', () => {
+ let component: AddMessageDialogComponent;
+ let fixture: ComponentFixture<AddMessageDialogComponent>;
+ let dialogRef = jasmine.createSpyObj('MatDialogRef', ['close']);
+ let dialogData: AddMessageDialog = {
+ id: '-1',
+ name: '',
+ description: '',
+ interfaceMessageNumber: '',
+ interfaceMessagePeriodicity: '',
+ interfaceMessageRate: '',
+ interfaceMessageType: '',
+ interfaceMessageWriteAccess:''
+ }
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports:[MatDialogModule,FormsModule,MatFormFieldModule,MatInputModule,MatButtonModule,NoopAnimationsModule],
+ declarations: [AddMessageDialogComponent],
+ providers: [{
+ provide: MatDialogRef, useValue: dialogRef
+ },{provide:MAT_DIALOG_DATA,useValue:dialogData}]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(AddMessageDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/add-message-dialog/add-message-dialog.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/add-message-dialog/add-message-dialog.component.ts
new file mode 100644
index 0000000..f4d1040
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/add-message-dialog/add-message-dialog.component.ts
@@ -0,0 +1,21 @@
+import { Component, Inject, OnInit } from '@angular/core';
+import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { AddMessageDialog } from '../../../types/AddMessageDialog';
+import { AddSubMessageDialogComponent } from '../../sub-message-table/add-sub-message-dialog/add-sub-message-dialog.component';
+
+@Component({
+ selector: 'app-add-message-dialog',
+ templateUrl: './add-message-dialog.component.html',
+ styleUrls: ['./add-message-dialog.component.sass']
+})
+export class AddMessageDialogComponent implements OnInit {
+
+ constructor(public dialogRef: MatDialogRef<AddSubMessageDialogComponent>, @Inject(MAT_DIALOG_DATA) public data: AddMessageDialog,) { }
+
+ ngOnInit(): void {
+ }
+
+ onNoClick() {
+ this.dialogRef.close();
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/edit-message-field/edit-message-field.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/edit-message-field/edit-message-field.component.html
new file mode 100644
index 0000000..c5359a6
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/edit-message-field/edit-message-field.component.html
@@ -0,0 +1,4 @@
+<mat-form-field>
+ <mat-label>{{header|convertMessageTableTitlesToString}}</mat-label>
+ <input matInput [(ngModel)]="value" (ngModelChange)="updateMessage(header,value)">
+</mat-form-field>
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/edit-message-field/edit-message-field.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/edit-message-field/edit-message-field.component.sass
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/edit-message-field/edit-message-field.component.sass
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/edit-message-field/edit-message-field.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/edit-message-field/edit-message-field.component.spec.ts
new file mode 100644
index 0000000..692fed2
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/edit-message-field/edit-message-field.component.spec.ts
@@ -0,0 +1,32 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { ConvertMessageTableTitlesToStringPipe } from '../../../pipes/convert-message-table-titles-to-string.pipe';
+
+import { EditMessageFieldComponent } from './edit-message-field.component';
+
+describe('EditMessageFieldComponent', () => {
+ let component: EditMessageFieldComponent;
+ let fixture: ComponentFixture<EditMessageFieldComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports:[HttpClientTestingModule,FormsModule,MatFormFieldModule,MatInputModule,NoopAnimationsModule],
+ declarations: [ EditMessageFieldComponent, ConvertMessageTableTitlesToStringPipe ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(EditMessageFieldComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/edit-message-field/edit-message-field.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/edit-message-field/edit-message-field.component.ts
new file mode 100644
index 0000000..b85ad80
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/edit-message-field/edit-message-field.component.ts
@@ -0,0 +1,49 @@
+import { Component, Input, OnInit } from '@angular/core';
+import { Subject } from 'rxjs';
+import { share, debounceTime, distinctUntilChanged, map, tap, switchMap } from 'rxjs/operators';
+import { CurrentMessagesService } from '../../../services/current-messages.service';
+
+interface message {
+ id: string,
+ name: string,
+ description: string ,
+ interfaceMessageRate: string ,
+ interfaceMessagePeriodicity: string ,
+ interfaceMessageWriteAccess: boolean ,
+ interfaceMessageType: string ,
+ interfaceMessageNumber:string
+}
+
+@Component({
+ selector: 'osee-messaging-edit-message-field',
+ templateUrl: './edit-message-field.component.html',
+ styleUrls: ['./edit-message-field.component.sass']
+})
+export class EditMessageFieldComponent implements OnInit {
+ @Input() messageId!: string;
+ @Input() header: string = '';
+ @Input() value: string = '';
+ private _value: Subject<string> = new Subject();
+ _message: Partial<message> = {
+ id:this.messageId
+ };
+ private _sendValue = this._value.pipe(
+ share(),
+ debounceTime(500),
+ distinctUntilChanged(),
+ map((x: any) => this._message[this.header as keyof message] = x),
+ tap(() => {
+ this._message.id = this.messageId;
+ }),
+ switchMap(val=>this.messageService.partialUpdateMessage(this._message))
+ )
+ constructor (private messageService: CurrentMessagesService) {
+ this._sendValue.subscribe();
+ }
+
+ ngOnInit(): void {
+ }
+ updateMessage(header: string, value: string) {
+ this._value.next(value);
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/message-table.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/message-table.component.html
new file mode 100644
index 0000000..55f073e
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/message-table.component.html
@@ -0,0 +1,56 @@
+<div class="message-interface message-element-interface-button-header">
+ <button mat-raised-button (click)="openSettingsDialog()" style="float:right">Settings</button>
+</div>
+<button *ngIf="editMode===true" mat-fab (click)="openNewMessageDialog()" class="new-message-button" color="primary">+</button>
+<div class="message-interface message-element-interface-top-level-table">
+ <mat-form-field class="message-interface-table-view-width-100 message-interface-table-filter-padding">
+ <mat-label>Filter Message Information</mat-label>
+ <input matInput type="text" (keyup)="applyFilter($event)" #input>
+ <mat-hint>Enter text to filter Message Table.
+ Only full text matches will display results.
+ <!-- To filter inner tables, use sub message: in the filter. -->
+ </mat-hint>
+ </mat-form-field>
+ <table mat-table [dataSource]="dataSource" multiTemplateDataRows class="mat-elevation-z8">
+ <ng-container [matColumnDef]="header" *ngFor="let header of headers; let i = index; trackBy:valueTracker;">
+ <th mat-header-cell *matHeaderCellDef [attr.colspan]="headers[i]" class="message-interface-table-view-message-header" [matTooltip]="header">
+ <ng-container>
+ {{header |convertMessageTableTitlesToString}}
+ </ng-container>
+ </th>
+ <td mat-cell *matCellDef="let element; let i = dataIndex" [ngClass]="i%2===0? 'message-table-row-even':'message-table-row-odd'">
+ <div class="flex-row">
+ <ng-container *ngIf="header==='name'">
+ <button mat-icon-button [@expandButton]="!expandedElement.includes(element.id) ? 'closed' : 'open'" (click)="rowChange(element.id,!expandedElement.includes(element.id))">V</button>
+ </ng-container>
+ <ng-container *ngIf="editMode===true;else no_edit">
+ <osee-messaging-edit-message-field [messageId]="element.id" [header]="header" [value]="element[header]"></osee-messaging-edit-message-field>
+ </ng-container>
+ <ng-template #no_edit>
+ <div appHighlightFilteredText [searchTerms]="searchTerms" [text]="element[header]" classToApply="ple-message-interface-table-highlighted-text">
+ {{element[header]}}
+ </div>
+ </ng-template>
+ </div>
+ </td>
+ </ng-container>
+ <ng-container matColumnDef="expandedMessage">
+ <td mat-cell *matCellDef="let element" [attr.colspan]="headers.length" class="no-pad">
+ <div class="sub-message-table-message-table-detail message-element-interface-table-view-width-100"
+ [@detailExpand]="expandedElement.includes(element.id) ? 'expanded' : 'collapsed'">
+ <ng-container *ngIf="expandedElement.includes(element.id)">
+ <ple-messaging-sub-message-table [data]="element.subMessages" [filter]="filter" [element]="element" (expandRow)="expandRow($event)" [editMode]="editMode"></ple-messaging-sub-message-table>
+ </ng-container>
+ </div>
+ </td>
+ </ng-container>
+ <tr mat-header-row *matHeaderRowDef="headers; sticky:true">
+ </tr>
+ <tr mat-row *matRowDef= "let row; columns: headers;"
+ class="message-detail-row"
+ [class.message-expanded-detail-row]="expandedElement.includes(row.id)">
+ </tr>
+ <tr mat-row *matRowDef="let row; columns: ['expandedMessage']" class="message-expanded-detail-row">
+ </tr>
+ </table>
+</div>
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/message-table.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/message-table.component.sass
new file mode 100644
index 0000000..b911ac8
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/message-table.component.sass
@@ -0,0 +1,31 @@
+table
+ width: 100%
+.message-interface-table-view-width-100
+ width: 100%
+.mat-header-cell
+ font:
+ size: 14px
+tr.message-expanded-detail-row
+ height: 0
+.message-detail-row td
+ border-bottom-width: 0
+.sub-message-table-message-table-detail
+ overflow: hidden
+ display: flex
+ flex-direction: column
+.message-interface-table-filter-padding
+ padding:
+ left: 1%
+ bottom: 1%
+.message-interface-table-view-message-header
+ font:
+ weight: bold
+.flex-row
+ display: flex
+ flex:
+ direction: row
+.new-message-button
+ z-index: 10
+ position: fixed
+ bottom: 3%
+ right: 2%
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/message-table.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/message-table.component.spec.ts
new file mode 100644
index 0000000..f1422f7
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/message-table.component.spec.ts
@@ -0,0 +1,130 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { HarnessLoader } from '@angular/cdk/testing';
+import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
+import { MatButtonHarness } from '@angular/material/button/testing';
+import { MatTableHarness } from '@angular/material/table/testing';
+import { MatFormFieldHarness } from '@angular/material/form-field/testing';
+import { MatInputHarness } from '@angular/material/input/testing';
+import { FormsModule } from '@angular/forms';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatTableModule } from '@angular/material/table';
+import { MatTooltipModule } from '@angular/material/tooltip';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { RouterTestingModule } from '@angular/router/testing';
+import { OseeStringUtilsDirectivesModule } from 'src/app/osee-utils/osee-string-utils/osee-string-utils-directives/osee-string-utils-directives.module';
+import { OseeStringUtilsPipesModule } from 'src/app/osee-utils/osee-string-utils/osee-string-utils-pipes/osee-string-utils-pipes.module';
+import { ConvertMessageTableTitlesToStringPipe } from '../../pipes/convert-message-table-titles-to-string.pipe';
+import { SubMessageTableComponent } from '../sub-message-table/sub-message-table.component';
+
+import { MessageTableComponent } from './message-table.component';
+import { CurrentMessagesService } from '../../services/current-messages.service';
+import { message } from '../../types/messages';
+import { BehaviorSubject, of } from 'rxjs';
+import { ConvertSubMessageTitlesToStringPipe } from '../../pipes/convert-sub-message-titles-to-string.pipe';
+import { MatMenuModule } from '@angular/material/menu';
+import { MatDialogModule } from '@angular/material/dialog';
+import { EditMessageFieldComponent } from './edit-message-field/edit-message-field.component';
+
+let loader: HarnessLoader;
+
+describe('MessageTableComponent', () => {
+ let component: MessageTableComponent;
+ let fixture: ComponentFixture<MessageTableComponent>;
+ let expectedData: message[] = [{
+ id:'-1',
+ name: 'name',
+ description: 'description',
+ interfaceMessageRate: '50Hz',
+ interfaceMessageNumber: '0',
+ interfaceMessagePeriodicity: '1Hz',
+ interfaceMessageWriteAccess: 'true',
+ interfaceMessageType: 'Connection',
+ subMessages: [{
+ id: '0',
+ name: 'sub message name',
+ description: '',
+ interfaceMessageRate: '50Hz',
+ interfaceSubMessageNumber:'0'
+ }]
+ }];
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [
+ FormsModule,
+ MatFormFieldModule,
+ MatInputModule,
+ MatTableModule,
+ OseeStringUtilsDirectivesModule,
+ OseeStringUtilsPipesModule,
+ NoopAnimationsModule,
+ MatTooltipModule,
+ MatMenuModule,
+ MatDialogModule,
+ RouterTestingModule
+ ],
+ declarations: [MessageTableComponent, ConvertMessageTableTitlesToStringPipe, SubMessageTableComponent, ConvertSubMessageTitlesToStringPipe, EditMessageFieldComponent],
+ providers: [{
+ provide: CurrentMessagesService, useValue: {
+ messages: of(expectedData),
+ BranchId:new BehaviorSubject("10")
+ }}]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(MessageTableComponent);
+ component = fixture.componentInstance;
+ loader = TestbedHarnessEnvironment.loader(fixture);
+ fixture.detectChanges();
+ });
+
+ beforeEach(function () {
+ var store:any = {};
+
+ spyOn(localStorage, 'getItem').and.callFake(function (key) {
+ return store[key];
+ });
+ spyOn(localStorage, 'setItem').and.callFake(function (key, value) {
+ return store[key] = value + '';
+ });
+ spyOn(localStorage, 'clear').and.callFake(function () {
+ store = {};
+ });
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should expand a row and hide a row on click', async () => {
+ expect(component).toBeTruthy();
+ const expandRow = spyOn(component, 'expandRow').and.callThrough();
+ const hideRow = spyOn(component, 'hideRow').and.callThrough();
+ let table = await loader.getHarness(MatTableHarness);
+ let buttons = await table.getAllHarnesses(MatButtonHarness);
+ await buttons[0].click();
+ await expect(expandRow).toHaveBeenCalled();
+ fixture.detectChanges();
+ await fixture.whenStable();
+ let hiddenButtons = await table.getAllHarnesses(MatButtonHarness);
+ await hiddenButtons[0].click();
+ expect(hideRow).toHaveBeenCalled();
+ });
+
+ it('should filter the top level table', async () => {
+ let form = await loader.getHarness(MatFormFieldHarness);
+ let input = await form.getControl(MatInputHarness);
+ await input?.focus();
+ //await input?.setValue('Hello');
+ })
+
+ // it('should filter the sub level table', async () => {
+ // don't know how to test yet
+ // let form = await loader.getHarness(MatFormFieldHarness);
+ // let input = await form.getControl(MatInputHarness);
+ // await input?.setValue('sub message: Hello');
+ // })
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/message-table.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/message-table.component.ts
new file mode 100644
index 0000000..10e3b67
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/message-table/message-table.component.ts
@@ -0,0 +1,147 @@
+import { trigger, state, style, transition, animate } from '@angular/animations';
+import { Component, OnInit } from '@angular/core';
+import { MatDialog } from '@angular/material/dialog';
+import { MatTableDataSource } from '@angular/material/table';
+import { ColumnPreferencesDialogComponent } from '../../../shared/components/dialogs/column-preferences-dialog/column-preferences-dialog.component';
+import { settingsDialogData } from '../../../shared/types/settingsdialog';
+import { CurrentMessagesService } from '../../services/current-messages.service';
+import { message } from '../../types/messages';
+import {branchStorage} from '../../../shared/types/branchstorage'
+import { AddMessageDialogComponent } from './add-message-dialog/add-message-dialog.component';
+import { AddMessageDialog } from '../../types/AddMessageDialog';
+import { filter, first, switchMap } from 'rxjs/operators';
+
+@Component({
+ selector: 'ple-messaging-message-table',
+ templateUrl: './message-table.component.html',
+ styleUrls: ['./message-table.component.sass'],
+ animations: [
+ trigger('detailExpand', [
+ state('collapsed', style({height: '0px', minHeight: '0'})),
+ state('expanded', style({height: '*'})),
+ transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
+ transition('collapsed <=> expanded', animate('225ms cubic-bezier(0.2, 1, 0.4, 0.0)'))
+ ]),
+ trigger('expandButton', [
+ state('closed', style({ transform: 'rotate(0)' })),
+ state('open', style({ transform: 'rotate(-180deg)' })),
+ transition('open => closed', animate('250ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
+ transition('closed => open', animate('250ms cubic-bezier(0.4, 0.0, 0.2, 1)'))
+ ])
+ ]
+})
+export class MessageTableComponent implements OnInit {
+ messageData = this.messageService.messages;
+ dataSource: MatTableDataSource<message> = new MatTableDataSource<message>();
+ headers: string[] = [];
+ expandedElement: Array<any> = [];
+ filter: string = "";
+ searchTerms: string = "";
+ editMode: boolean = false;
+ constructor (private messageService: CurrentMessagesService,public dialog: MatDialog) {
+ this.messageData.subscribe((value) => {
+ this.dataSource.data = value;
+ })
+ this.headers = ["name","description","interfaceMessageNumber","interfaceMessagePeriodicity","interfaceMessageRate","interfaceMessageWriteAccess","interfaceMessageType"];
+ }
+
+ ngOnInit(): void {
+ let branchStorage = JSON.parse(
+ localStorage.getItem(this.messageService.BranchId.getValue()) || '{}'
+ ) as branchStorage;
+ if (branchStorage?.mim?.editMode) {
+ this.editMode = branchStorage.mim.editMode;
+ }
+ }
+ expandRow(value: any) {
+ if (this.expandedElement.indexOf(value)===-1) {
+ this.expandedElement.push(value);
+ }
+ }
+ hideRow(value: any) {
+ let index = this.expandedElement.indexOf(value);
+ if (index > -1) {
+ this.expandedElement.splice(index,1)
+ }
+ }
+
+ rowChange(value: any, type: boolean) {
+ if (type) {
+ this.expandRow(value);
+ } else {
+ this.hideRow(value);
+ }
+ }
+
+ applyFilter(event: Event) {
+ const filterValue = (event.target as HTMLInputElement).value;
+ this.searchTerms = filterValue;
+ this.messageService.filter = filterValue.trim().toLowerCase();
+ this.filter = filterValue.trim().toLowerCase();
+ }
+ valueTracker(index: any, item: any) {
+ return index;
+ }
+
+ openSettingsDialog() {
+ let dialogData: settingsDialogData = {
+ branchId: this.messageService.BranchId.getValue(),
+ allHeaders2: [],
+ allowedHeaders2: [],
+ allHeaders1: [],
+ allowedHeaders1: [],
+ editable: this.editMode,
+ headers1Label: 'Structure Headers',
+ headers2Label: 'Element Headers',
+ headersTableActive: false,
+ };
+ const dialogRef = this.dialog.open(ColumnPreferencesDialogComponent, {
+ data: dialogData,
+ });
+ dialogRef.afterClosed().subscribe((result: settingsDialogData) => {
+ //this.allowedElementHeaders = result.allowedHeaders2;
+ //this.allowedStructureHeaders = result.allowedHeaders1;
+ this.editMode = result.editable;
+ //@todo: remove when user preferences are available on backend
+ if (localStorage.getItem(this.messageService.BranchId.getValue())) {
+ let branchStorage = JSON.parse(
+ localStorage.getItem(this.messageService.BranchId.getValue()) ||
+ '{}'
+ ) as branchStorage;
+ branchStorage.mim['editMode'] = result.editable;
+ localStorage.setItem(
+ this.messageService.BranchId.getValue(),
+ JSON.stringify(branchStorage)
+ );
+ } else {
+ localStorage.setItem(
+ this.messageService.BranchId.getValue(),
+ JSON.stringify({
+ mim: {
+ editMode: result.editable,
+ },
+ })
+ );
+ }
+ });
+ }
+ openNewMessageDialog() {
+ let dialogData: Partial<AddMessageDialog> = {
+ name: '',
+ description: '',
+ interfaceMessageNumber: '',
+ interfaceMessagePeriodicity: '',
+ interfaceMessageRate: '',
+ interfaceMessageType: '',
+ interfaceMessageWriteAccess: ''
+ };
+ const dialogRef = this.dialog.open(AddMessageDialogComponent, {
+ data: dialogData
+ });
+ dialogRef.afterClosed().pipe(
+ filter((val) => val !== undefined),
+ switchMap((val) => this.messageService.createMessage(val)),
+ first()
+ ).subscribe();
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/add-sub-message-dialog/add-sub-message-dialog.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/add-sub-message-dialog/add-sub-message-dialog.component.html
new file mode 100644
index 0000000..d48566b
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/add-sub-message-dialog/add-sub-message-dialog.component.html
@@ -0,0 +1,56 @@
+<h1 mat-dialog-title>Add Sub Message to Message {{data.name}}</h1>
+<mat-horizontal-stepper #stepper class ="new-submessage-stepper">
+ <mat-step label="Select Sub Message options" #step1>
+ <div style="display:flex; flex-direction:row; justify-content: space-evenly; align-items: baseline;">
+ <button mat-raised-button color="primary" style="width:100%;" matStepperNext (click)="createNew()">Create new Sub Message</button>
+ <p style="width:100%; text-align:center;">or</p>
+ <mat-form-field style="width:100%;">
+ <mat-label>Select a Sub Message to Add to Message</mat-label>
+ <mat-select [(ngModel)]="data.subMessage" (selectionChange)="storeId($event.value)">
+ <mat-option *ngFor="let option of (availableSubMessages|async)" [value]="option" [id]="option!==undefined && option.id !==undefined ? option.id :''" >
+ {{option.name}}
+ </mat-option>
+ </mat-select>
+ </mat-form-field>
+ </div>
+ <button mat-raised-button color="primary" *ngIf="data.subMessage?.id && data.subMessage?.id!=='-1'" (click)="moveToReview(stepper)">Proceed to Review</button>
+ </mat-step>
+ <mat-step label="Define Sub Message" #step2>
+ <div style="display:flex; flex-direction:column">
+ <mat-form-field>
+ <mat-label>Name</mat-label>
+ <input matInput [(ngModel)]="data.subMessage.name" required>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>Description</mat-label>
+ <input matInput [(ngModel)]="data.subMessage.description" required>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>Message Rate</mat-label>
+ <input matInput [(ngModel)]="data.subMessage.interfaceMessageRate" required>
+ </mat-form-field>
+ <mat-form-field>
+ <mat-label>Sub Message Number</mat-label>
+ <input matInput [(ngModel)]="data.subMessage.interfaceSubMessageNumber" required>
+ </mat-form-field>
+ </div>
+ <button mat-raised-button matStepperPrevious>Back</button>
+ <button mat-raised-button color="primary" *ngIf="data.subMessage.name.length>0 && data.subMessage.description.length>0 && data.subMessage.interfaceMessageRate.length>0 && data.subMessage.interfaceSubMessageNumber.length>0" matStepperNext>Next</button>
+ </mat-step>
+ <mat-step label="Review" #step3>
+ <div style="display:flex;flex-direction:column">
+ A sub message will be related to:
+ <mat-label>{{data.name}}</mat-label> with the following properties:
+ <mat-label>Sub Message Name: {{data.subMessage?.name}}</mat-label>
+ <mat-label>Sub Message Description: {{data.subMessage?.description}}</mat-label>
+ <mat-label>Sub Message Rate: {{data.subMessage?.interfaceMessageRate}}</mat-label>
+ <mat-label>Sub Message Number: {{data.subMessage?.interfaceSubMessageNumber}}</mat-label>
+ </div>
+ <mat-dialog-actions align="end">
+ <button mat-button matStepperPrevious>Back</button>
+ <button mat-raised-button color="primary" [mat-dialog-close]="data">
+ Ok
+ </button>
+ </mat-dialog-actions>
+ </mat-step>
+</mat-horizontal-stepper>
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/add-sub-message-dialog/add-sub-message-dialog.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/add-sub-message-dialog/add-sub-message-dialog.component.sass
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/add-sub-message-dialog/add-sub-message-dialog.component.sass
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/add-sub-message-dialog/add-sub-message-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/add-sub-message-dialog/add-sub-message-dialog.component.spec.ts
new file mode 100644
index 0000000..6a5727a
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/add-sub-message-dialog/add-sub-message-dialog.component.spec.ts
@@ -0,0 +1,84 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatSelectModule } from '@angular/material/select';
+import { MatStepperModule } from '@angular/material/stepper';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { AddSubMessageDialog } from '../../../types/AddSubMessageDialog';
+import { subMessage } from '../../../types/sub-messages';
+
+import { AddSubMessageDialogComponent } from './add-sub-message-dialog.component';
+
+describe('AddSubMessageDialogComponent', () => {
+ let component: AddSubMessageDialogComponent;
+ let fixture: ComponentFixture<AddSubMessageDialogComponent>;
+ let dialogRef = jasmine.createSpyObj('MatDialogRef', ['close']);
+ let dialogData: AddSubMessageDialog = {
+ id: '123456',
+ name: 'message',
+ subMessage: {
+ name: '',
+ description: '',
+ interfaceMessageRate: '',
+ interfaceSubMessageNumber:''
+ }
+ }
+ let dummySubmessage: subMessage = {
+ id: '10',
+ name: '',
+ description: '',
+ interfaceMessageRate: '',
+ interfaceSubMessageNumber:''
+ }
+ let httpTestingController: HttpTestingController;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports:[HttpClientTestingModule,NoopAnimationsModule,MatDialogModule,MatStepperModule,FormsModule,MatFormFieldModule,MatInputModule,MatButtonModule,MatSelectModule,],
+ declarations: [AddSubMessageDialogComponent],
+ providers:[{provide:MatDialogRef,useValue:dialogRef},{provide:MAT_DIALOG_DATA,useValue:dialogData}]
+ })
+ .compileComponents();
+ httpTestingController = TestBed.inject(HttpTestingController);
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(AddSubMessageDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should movetoStep', () => {
+ let stepper = jasmine.createSpyObj('stepper', {}, { selectedIndex: 0 });
+ spyOn(stepper, 'selectedIndex').and.callThrough();
+ component.moveToStep(3, stepper);
+ expect(stepper.selectedIndex).toEqual(0);
+ });
+
+ it('should create new by setting id to -1', () => {
+ component.createNew();
+ expect(component.data.subMessage.id).toEqual('-1');
+ });
+
+ it('should store the id', () => {
+ component.storeId(dummySubmessage);
+ expect(component.storedId).toEqual('10');
+ });
+
+ it('should movetoStep 3', () => {
+ let stepper = jasmine.createSpyObj('stepper', {}, { selectedIndex: 0 });
+ spyOn(stepper, 'selectedIndex').and.callThrough();
+ let spy = spyOn(component, 'moveToStep').and.stub();
+ component.moveToReview(stepper);
+ expect(spy).toHaveBeenCalled();
+ expect(spy).toHaveBeenCalledWith(3, stepper);
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/add-sub-message-dialog/add-sub-message-dialog.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/add-sub-message-dialog/add-sub-message-dialog.component.ts
new file mode 100644
index 0000000..8e3384d
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/add-sub-message-dialog/add-sub-message-dialog.component.ts
@@ -0,0 +1,51 @@
+import { Component, Inject, OnInit } from '@angular/core';
+import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatStepper } from '@angular/material/stepper';
+import { map, mergeAll, mergeMap,scan, share} from 'rxjs/operators';
+import { CurrentMessagesService } from '../../../services/current-messages.service';
+import { AddSubMessageDialog } from '../../../types/AddSubMessageDialog';
+import { subMessage } from '../../../types/sub-messages';
+
+@Component({
+ selector: 'app-add-sub-message-dialog',
+ templateUrl: './add-sub-message-dialog.component.html',
+ styleUrls: ['./add-sub-message-dialog.component.sass']
+})
+export class AddSubMessageDialogComponent implements OnInit {
+
+ availableSubMessages = this.messageService.allMessages.pipe(
+ mergeMap(x=>x),
+ map(x => x?.subMessages),
+ mergeAll(),
+ scan((acc, curr) => [...acc, curr], [] as subMessage[]),
+ map((y) => y.sort((a, b) => { return a.id!=undefined && b.id!=undefined && a.id > b.id ? -1 : 1 })),
+ map((y) => y.filter((val, index, array) => {
+ return !index || val.id != array[index - 1].id;
+ })),
+ map((y) => y.sort((a, b) => { return a.name > b.name ? -1 : 1 })),
+ share()
+ )
+ storedId: string = '-1';
+ constructor (public dialogRef: MatDialogRef<AddSubMessageDialogComponent>, @Inject(MAT_DIALOG_DATA) public data: AddSubMessageDialog, private messageService: CurrentMessagesService) {
+ }
+
+ ngOnInit(): void {
+ }
+
+ moveToStep(index: number, stepper: MatStepper) {
+ stepper.selectedIndex = index - 1;
+ }
+
+ createNew() {
+ this.data.subMessage.id = '-1';
+ }
+
+ storeId(value: subMessage) {
+ this.storedId = value.id || '-1';
+ }
+
+ moveToReview(stepper: MatStepper) {
+ this.data.subMessage.id = this.storedId;
+ this.moveToStep(3, stepper);
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/edit-sub-message-field/edit-sub-message-field.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/edit-sub-message-field/edit-sub-message-field.component.html
new file mode 100644
index 0000000..6b75e82
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/edit-sub-message-field/edit-sub-message-field.component.html
@@ -0,0 +1,4 @@
+<mat-form-field>
+ <mat-label>{{header|convertSubMessageTitlesToString}}</mat-label>
+ <input matInput [(ngModel)]="value" (ngModelChange)="updateSubMessage(header,value)">
+</mat-form-field>
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/edit-sub-message-field/edit-sub-message-field.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/edit-sub-message-field/edit-sub-message-field.component.sass
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/edit-sub-message-field/edit-sub-message-field.component.sass
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/edit-sub-message-field/edit-sub-message-field.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/edit-sub-message-field/edit-sub-message-field.component.spec.ts
new file mode 100644
index 0000000..8090c40
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/edit-sub-message-field/edit-sub-message-field.component.spec.ts
@@ -0,0 +1,32 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { ConvertSubMessageTitlesToStringPipe } from '../../../pipes/convert-sub-message-titles-to-string.pipe';
+
+import { EditSubMessageFieldComponent } from './edit-sub-message-field.component';
+
+describe('EditSubMessageFieldComponent', () => {
+ let component: EditSubMessageFieldComponent;
+ let fixture: ComponentFixture<EditSubMessageFieldComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports:[FormsModule,MatFormFieldModule,MatInputModule,NoopAnimationsModule,HttpClientTestingModule,],
+ declarations: [ EditSubMessageFieldComponent,ConvertSubMessageTitlesToStringPipe ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(EditSubMessageFieldComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/edit-sub-message-field/edit-sub-message-field.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/edit-sub-message-field/edit-sub-message-field.component.ts
new file mode 100644
index 0000000..29786bb
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/edit-sub-message-field/edit-sub-message-field.component.ts
@@ -0,0 +1,42 @@
+import { Component, Input, OnInit } from '@angular/core';
+import { Observable, of, Subject } from 'rxjs';
+import { share, debounceTime, distinctUntilChanged, map, switchMap, tap } from 'rxjs/operators';
+import { CurrentMessagesService } from '../../../services/current-messages.service';
+import { subMessage } from '../../../types/sub-messages';
+
+@Component({
+ selector: 'osee-messaging-edit-sub-message-field',
+ templateUrl: './edit-sub-message-field.component.html',
+ styleUrls: ['./edit-sub-message-field.component.sass']
+})
+export class EditSubMessageFieldComponent implements OnInit {
+
+ @Input() messageId!: string;
+ @Input() subMessageId!: string ;
+ @Input() header: string = '';
+ @Input() value: string = '';
+ private _value: Subject<string> = new Subject();
+ _subMessage: Partial<subMessage> = {
+ id:this.subMessageId
+ };
+ private _sendValue = this._value.pipe(
+ share(),
+ debounceTime(500),
+ distinctUntilChanged(),
+ map((x: string) => this._subMessage[this.header as keyof subMessage] = x),
+ tap(() => {
+ this._subMessage.id = this.subMessageId;
+ }),
+ switchMap(val=>this.messageService.partialUpdateSubMessage(this._subMessage,this.messageId))
+ )
+ constructor (private messageService: CurrentMessagesService) {
+ this._sendValue.subscribe();
+ }
+
+ ngOnInit(): void {
+ }
+
+ updateSubMessage(header: string, value: string) {
+ this._value.next(value);
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/sub-message-table.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/sub-message-table.component.html
new file mode 100644
index 0000000..8ae0ac9
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/sub-message-table.component.html
@@ -0,0 +1,51 @@
+<div class="message-interface-table-view mat-elevation-z9">
+ <table mat-table [dataSource]="dataSource" class="message-interface-table-view-width-100">
+ <ng-container [matColumnDef]="header" *ngFor="let header of headers;let j=index;trackBy:valueTracker">
+ <th mat-header-cell *matHeaderCellDef class="message-interface-table-view-sub-message-header">{{header |convertSubMessageTitlesToString}}</th>
+ <td mat-cell *matCellDef="let value" class="message-interface-table-center">
+ <ng-container *ngIf="editMode==false; else edit_Mode;">
+ <ng-container *ngIf="header==='description'">
+ <div appHighlightFilteredText [searchTerms]="filter" [text]="value[header] | displayTruncatedStringWithFieldOverflow:75" classToApply="ple-message-interface-table-highlighted-text">
+ {{value[header] | displayTruncatedStringWithFieldOverflow:75}}
+ </div>
+ </ng-container>
+ <ng-container *ngIf="header!=='description' && header!==' '">
+ <div appHighlightFilteredText [searchTerms]="filter" [text]="value[header]" classToApply="ple-message-interface-table-highlighted-text">
+ {{value[header]}}
+ </div>
+ </ng-container>
+ <ng-container *ngIf="header===' '"><button mat-raised-button (click)="navigateToElementsTable(element.id,value['id'],element.name+' > '+value['name'])" (contextmenu)="openMenu($event,element.id,value['id'],element.name+' > '+value['name'])">Go To Message Details</button>
+ </ng-container>
+ </ng-container>
+ <ng-template #edit_Mode>
+ <ng-container *ngIf="header!==' '">
+ <osee-messaging-edit-sub-message-field [messageId]="element.id" [subMessageId]="value['id']" [header]="header" [value]="value[header]"></osee-messaging-edit-sub-message-field>
+ </ng-container>
+ <ng-container *ngIf="header===' '">
+ <button mat-raised-button (click)="navigateToElementsTable(element.id,value['id'],element.name+' > '+value['name'])" (contextmenu)="openMenu($event,element.id,value['id'],element.name+' > '+value['name'])">Go To Message Details</button>
+ </ng-container>
+ </ng-template>
+ </td>
+ </ng-container>
+ <ng-container matColumnDef="footer">
+ <td mat-footer-cell *matFooterCellDef [attr.colspan]="headers.length" style="text-align:right">
+ <ng-container *ngIf="editMode===true;">
+ <button mat-mini-fab color="primary" (click)="createNewSubMessage()">+</button>
+ </ng-container>
+ </td>
+ </ng-container>
+ <tr mat-header-row *matHeaderRowDef="headers;"></tr>
+ <tr mat-row *matRowDef= "let row2; columns: headers; let k=index;"
+ [ngClass]="k%2===0? 'message-table-sub-message-row-even':'message-table-sub-message-row-odd'"></tr>
+ <tr mat-footer-row *matFooterRowDef="['footer']"></tr>
+ </table>
+</div>
+<mat-menu #contextMenu="matMenu">
+ <ng-template matMenuContent let-id="id" let-submessage="submessage" let-location="location">
+ <button mat-menu-item (click)="navigateToElementsTableInNewTab(id,submessage,location)"> Open in new tab</button>
+ </ng-template>
+</mat-menu>
+<div style="visibility: hidden; position: fixed;"
+[style.left]="menuPosition.x"
+[style.top]="menuPosition.y"
+[matMenuTriggerFor]="contextMenu"></div>
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/sub-message-table.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/sub-message-table.component.sass
new file mode 100644
index 0000000..a2f74fd
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/sub-message-table.component.sass
@@ -0,0 +1,12 @@
+.message-interface-table-view-width-100
+ width:100%
+.mat-header-cell
+ font:
+ size: 14px
+.message-interface-table-center
+ text-align: center
+.message-interface-table-view-sub-message-header
+ font:
+ weight: 500
+ text:
+ align: center
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/sub-message-table.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/sub-message-table.component.spec.ts
new file mode 100644
index 0000000..16137df
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/sub-message-table.component.spec.ts
@@ -0,0 +1,89 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { SimpleChange } from '@angular/core';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MatButtonModule } from '@angular/material/button';
+import { MatDialogModule } from '@angular/material/dialog';
+import { MatMenuModule } from '@angular/material/menu';
+import { MatTableDataSource, MatTableModule } from '@angular/material/table';
+import { Router, ActivatedRoute, convertToParamMap } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
+import { of } from 'rxjs';
+import { OseeStringUtilsDirectivesModule } from 'src/app/osee-utils/osee-string-utils/osee-string-utils-directives/osee-string-utils-directives.module';
+import { OseeStringUtilsPipesModule } from 'src/app/osee-utils/osee-string-utils/osee-string-utils-pipes/osee-string-utils-pipes.module';
+import { MessageInterfaceComponent } from '../../message-interface.component';
+import { ConvertMessageTableTitlesToStringPipe } from '../../pipes/convert-message-table-titles-to-string.pipe';
+import { ConvertSubMessageTitlesToStringPipe } from '../../pipes/convert-sub-message-titles-to-string.pipe';
+import { MessageTableComponent } from '../message-table/message-table.component';
+import { AddSubMessageDialogComponent } from './add-sub-message-dialog/add-sub-message-dialog.component';
+import { EditSubMessageFieldComponent } from './edit-sub-message-field/edit-sub-message-field.component';
+
+import { SubMessageTableComponent } from './sub-message-table.component';
+
+describe('SubMessageTableComponent', () => {
+ let component: SubMessageTableComponent;
+ let fixture: ComponentFixture<SubMessageTableComponent>;
+ let router: any;
+ let expectedData = [
+ {
+ name: "Name",
+ description: "description adslkfj;asjfadkljf;lajdfla;jsdfdlkasjf;lkajslfjad;ljfkladjsf;",
+ interfaceSubMessageNumber: "0",
+ interfaceMessageRate:"1Hz"
+ },
+ {
+ name: "Name2",
+ description: "description2",
+ interfaceSubMessageNumber: "1",
+ interfaceMessageRate:"1Hz"
+ }
+]
+
+ beforeEach(async () => {
+ router = jasmine.createSpyObj('Router', ['navigate', 'createUrlTree', 'serializeUrl']);
+ await TestBed.configureTestingModule({
+ imports:[MatTableModule, MatButtonModule,OseeStringUtilsDirectivesModule,OseeStringUtilsPipesModule, RouterTestingModule, MatMenuModule, MatDialogModule, HttpClientTestingModule],
+ declarations: [SubMessageTableComponent, ConvertMessageTableTitlesToStringPipe, ConvertSubMessageTitlesToStringPipe, EditSubMessageFieldComponent, AddSubMessageDialogComponent],
+ providers: [{ provide: Router, useValue: router },
+ {
+ provide: ActivatedRoute, useValue: {
+ // paramMap: of(
+ // convertToParamMap(
+ // {
+ // name:"Name > Name"
+ // }
+ // )
+ // )
+ //
+ }
+ },
+ ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(SubMessageTableComponent);
+ component = fixture.componentInstance;
+ component.dataSource = new MatTableDataSource();
+ component.data = expectedData;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should navigate to Hello/10/10/elements', () => {
+ component.navigateToElementsTable("10","10",'Hello');
+ expect(router.navigate).toHaveBeenCalledWith(['10','10','Hello','elements'],{relativeTo: Object({ }), queryParamsHandling:'merge'});
+ });
+
+ it('should update the datasource filter', () => {
+ component.filter = "sub message: Name2";
+ component.ngOnChanges({
+ data: new SimpleChange(component.data, component.data, false),
+ filter: new SimpleChange('', component.filter, false)
+ })
+ expect(component.dataSource.filter === component.filter.replace('sub message: ', ''));
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/sub-message-table.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/sub-message-table.component.ts
new file mode 100644
index 0000000..8340cdb
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/components/sub-message-table/sub-message-table.component.ts
@@ -0,0 +1,98 @@
+import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core';
+import { MatDialog } from '@angular/material/dialog';
+import { MatMenuTrigger } from '@angular/material/menu';
+import { MatTableDataSource } from '@angular/material/table';
+import { ActivatedRoute, Router } from '@angular/router';
+import { iif } from 'rxjs';
+import { filter, switchMap, tap } from 'rxjs/operators';
+import { CurrentMessagesService } from '../../services/current-messages.service';
+import { AddSubMessageDialog } from '../../types/AddSubMessageDialog';
+import { message } from '../../types/messages';
+import { subMessage } from '../../types/sub-messages';
+import { AddSubMessageDialogComponent } from './add-sub-message-dialog/add-sub-message-dialog.component';
+
+@Component({
+ selector: 'ple-messaging-sub-message-table',
+ templateUrl: './sub-message-table.component.html',
+ styleUrls: ['./sub-message-table.component.sass']
+})
+export class SubMessageTableComponent implements OnInit, OnChanges {
+ @Input() data: subMessage[] = [];
+ @Input() dataSource: MatTableDataSource<subMessage> = new MatTableDataSource<subMessage>();
+ @Input() filter: string = "";
+
+ @Input() element!: message;
+ @Input() editMode: boolean = false;
+ @Output() expandRow = new EventEmitter();
+ headers: string[] = [];
+ menuPosition = {
+ x: '0',
+ y:'0'
+ }
+ @ViewChild(MatMenuTrigger, { static: true })
+ matMenuTrigger!: MatMenuTrigger;
+ constructor(public dialog: MatDialog,private route: ActivatedRoute, private router: Router,private messageService: CurrentMessagesService) {
+ this.dataSource.data = this.data;
+ this.headers=["name","description","interfaceSubMessageNumber","interfaceMessageRate", " "]
+ }
+ ngOnChanges(changes: SimpleChanges): void {
+ this.dataSource.data = this.data;
+ if (this.filter !== "") {
+ if (this.dataSource.filteredData.length > 0) {
+ this.expandRow.emit(this.element);
+ }
+ }
+ }
+
+ ngOnInit(): void {
+ }
+ valueTracker(index: any, item: any) {
+ return index;
+ }
+
+ navigateToElementsTable(id: string | undefined, submessage: string, location: string) {
+ this.router.navigate([id,submessage,location, 'elements'], {
+ relativeTo: this.route,
+ queryParamsHandling: 'merge',
+ })
+ }
+
+ openMenu(event: MouseEvent, id: string | undefined, submessage: string, location: string) {
+ event.preventDefault();
+ this.menuPosition.x = event.clientX + 'px';
+ this.menuPosition.y = event.clientY + 'px';
+ this.matMenuTrigger.menuData = {
+ id: id,
+ submessage: submessage,
+ location:location
+ }
+ this.matMenuTrigger.openMenu();
+ }
+ navigateToElementsTableInNewTab(id: string | undefined, submessage: string, location: string) {
+ const url = this.router.serializeUrl(this.router.createUrlTree([id,submessage,location, 'elements'], {
+ relativeTo: this.route,
+ queryParamsHandling: 'merge',
+ }))
+ window.open(url, "_blank");
+ }
+
+ createNewSubMessage() {
+ const dialogRef = this.dialog.open(AddSubMessageDialogComponent, {
+ data: {
+ name:this.element.name,
+ id: this.element.id,
+ subMessage: {
+ name: '',
+ description: '',
+ interfaceMessageRate: '',
+ interfaceSubMessageNumber:''
+ }
+ }
+ })
+ dialogRef.afterClosed().pipe(
+ filter((val)=>val!==undefined),
+ switchMap((z: AddSubMessageDialog) => iif(() => z != undefined && z.subMessage != undefined && z.subMessage.id != undefined && z?.subMessage?.id.length > 0 && z.subMessage.id!=='-1', this.messageService.relateSubMessage(z.id, z?.subMessage?.id || '-1'), this.messageService.createSubMessage(z.subMessage, z.id)))
+ ).subscribe();
+ }
+
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface-routing.module.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface-routing.module.ts
new file mode 100644
index 0000000..4f39b5c
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface-routing.module.ts
@@ -0,0 +1,11 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { MessageInterfaceComponent } from './message-interface.component';
+
+const routes: Routes = [{ path: '', component: MessageInterfaceComponent }];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule]
+})
+export class MessageInterfaceRoutingModule { }
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface.component.html
new file mode 100644
index 0000000..44fd309
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface.component.html
@@ -0,0 +1,4 @@
+<ng-container *ngIf="(isLoading|async)==='true'">
+ <mat-progress-bar mode="indeterminate"></mat-progress-bar>
+</ng-container>
+<ple-messaging-message-table></ple-messaging-message-table>
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface.component.sass
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface.component.sass
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface.component.spec.ts
new file mode 100644
index 0000000..a8f3cec
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface.component.spec.ts
@@ -0,0 +1,83 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatDialogModule } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatMenuModule } from '@angular/material/menu';
+import { MatTableModule } from '@angular/material/table';
+import { MatTooltipModule } from '@angular/material/tooltip';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { RouterTestingModule } from '@angular/router/testing';
+import { BehaviorSubject, of } from 'rxjs';
+import { OseeStringUtilsDirectivesModule } from 'src/app/osee-utils/osee-string-utils/osee-string-utils-directives/osee-string-utils-directives.module';
+import { OseeStringUtilsPipesModule } from 'src/app/osee-utils/osee-string-utils/osee-string-utils-pipes/osee-string-utils-pipes.module';
+import { AddMessageDialogComponent } from './components/message-table/add-message-dialog/add-message-dialog.component';
+import { EditMessageFieldComponent } from './components/message-table/edit-message-field/edit-message-field.component';
+import { MessageTableComponent } from './components/message-table/message-table.component';
+import { AddSubMessageDialogComponent } from './components/sub-message-table/add-sub-message-dialog/add-sub-message-dialog.component';
+import { EditSubMessageFieldComponent } from './components/sub-message-table/edit-sub-message-field/edit-sub-message-field.component';
+import { SubMessageTableComponent } from './components/sub-message-table/sub-message-table.component';
+
+import { MessageInterfaceComponent } from './message-interface.component';
+import { ConvertMessageTableTitlesToStringPipe } from './pipes/convert-message-table-titles-to-string.pipe';
+import { ConvertSubMessageTitlesToStringPipe } from './pipes/convert-sub-message-titles-to-string.pipe';
+import { CurrentMessagesService } from './services/current-messages.service';
+import { message } from './types/messages';
+
+describe('MessageInterfaceComponent', () => {
+ let component: MessageInterfaceComponent;
+ let fixture: ComponentFixture<MessageInterfaceComponent>;
+ let expectedData: message[] = [{
+ id:'-1',
+ name: 'name',
+ description: 'description',
+ interfaceMessageRate: '50Hz',
+ interfaceMessageNumber: '0',
+ interfaceMessagePeriodicity: '1Hz',
+ interfaceMessageWriteAccess: 'true',
+ interfaceMessageType: 'Connection',
+ subMessages: [{
+ id: '0',
+ name: 'sub message name',
+ description: '',
+ interfaceMessageRate: '50Hz',
+ interfaceSubMessageNumber:'0'
+ }]
+ }];
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [
+ MatTableModule,
+ MatFormFieldModule,
+ MatMenuModule,
+ FormsModule,
+ MatInputModule,
+ NoopAnimationsModule,
+ RouterTestingModule,
+ MatTooltipModule,
+ OseeStringUtilsDirectivesModule,
+ OseeStringUtilsPipesModule,
+ MatDialogModule],
+ declarations: [MessageInterfaceComponent, MessageTableComponent, SubMessageTableComponent, ConvertMessageTableTitlesToStringPipe, ConvertSubMessageTitlesToStringPipe, EditSubMessageFieldComponent, AddSubMessageDialogComponent, EditMessageFieldComponent, AddMessageDialogComponent],
+ providers: [{
+ provide: CurrentMessagesService, useValue: {
+ filter: '',
+ string: '',
+ messages: of(expectedData),
+ BranchId:new BehaviorSubject("10")
+ }}]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(MessageInterfaceComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface.component.ts
new file mode 100644
index 0000000..3254aec
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface.component.ts
@@ -0,0 +1,23 @@
+import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { HttpLoadingService } from '../shared/services/ui/http-loading.service';
+import { CurrentMessagesService } from './services/current-messages.service';
+
+@Component({
+ selector: 'app-message-interface',
+ templateUrl: './message-interface.component.html',
+ styleUrls: ['./message-interface.component.sass']
+})
+export class MessageInterfaceComponent implements OnInit {
+
+ isLoading = this.loadingService.isLoading;
+ constructor(private route: ActivatedRoute, private messageService: CurrentMessagesService, private loadingService: HttpLoadingService) { }
+
+ ngOnInit(): void {
+ this.route.paramMap.subscribe((values) => {
+ this.messageService.filter = values.get('type')?.trim().toLowerCase() || '';
+ this.messageService.branch = values.get('branchId') || '';
+ })
+ }
+
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface.module.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface.module.ts
new file mode 100644
index 0000000..b63a1fc
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/message-interface.module.ts
@@ -0,0 +1,53 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { MessageInterfaceRoutingModule } from './message-interface-routing.module';
+import { MessageInterfaceComponent } from './message-interface.component';
+import { MessageTableComponent } from './components/message-table/message-table.component';
+import { SubMessageTableComponent } from './components/sub-message-table/sub-message-table.component';
+import { PleSharedMaterialModule } from '../../ple-shared-material/ple-shared-material.module';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatTableModule } from '@angular/material/table';
+import { MatTooltipModule } from '@angular/material/tooltip';
+import { OseeStringUtilsDirectivesModule } from 'src/app/osee-utils/osee-string-utils/osee-string-utils-directives/osee-string-utils-directives.module';
+import { OseeStringUtilsPipesModule } from 'src/app/osee-utils/osee-string-utils/osee-string-utils-pipes/osee-string-utils-pipes.module';
+import { ConvertMessageTableTitlesToStringPipe } from './pipes/convert-message-table-titles-to-string.pipe';
+import { ConvertSubMessageTitlesToStringPipe } from './pipes/convert-sub-message-titles-to-string.pipe';
+import { MatMenuModule } from '@angular/material/menu';
+import { SharedMessagingModule } from '../shared/shared-messaging.module';
+import { MatDialogModule } from '@angular/material/dialog';
+import { FormsModule } from '@angular/forms';
+import { EditSubMessageFieldComponent } from './components/sub-message-table/edit-sub-message-field/edit-sub-message-field.component';
+import { AddSubMessageDialogComponent } from './components/sub-message-table/add-sub-message-dialog/add-sub-message-dialog.component';
+import { MatStepperModule } from '@angular/material/stepper';
+import { MatSelectModule } from '@angular/material/select';
+import { EditMessageFieldComponent } from './components/message-table/edit-message-field/edit-message-field.component';
+import { AddMessageDialogComponent } from './components/message-table/add-message-dialog/add-message-dialog.component';
+import { MatProgressBarModule } from '@angular/material/progress-bar';
+import { MatSlideToggleModule } from '@angular/material/slide-toggle';
+
+
+@NgModule({
+ declarations: [MessageInterfaceComponent, MessageTableComponent, SubMessageTableComponent, ConvertMessageTableTitlesToStringPipe, ConvertSubMessageTitlesToStringPipe, EditSubMessageFieldComponent, AddSubMessageDialogComponent, EditMessageFieldComponent, AddMessageDialogComponent],
+ imports: [
+ CommonModule,
+ FormsModule,
+ MatTableModule,
+ MatMenuModule,
+ MatStepperModule,
+ MatSelectModule,
+ MatFormFieldModule,
+ MatInputModule,
+ MatSlideToggleModule,
+ MatTooltipModule,
+ MatDialogModule,
+ MatProgressBarModule,
+ PleSharedMaterialModule,
+ OseeStringUtilsPipesModule,
+ OseeStringUtilsDirectivesModule,
+ SharedMessagingModule,
+ MessageInterfaceRoutingModule
+ ]
+})
+export class MessageInterfaceModule { }
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/pipes/convert-message-table-titles-to-string.pipe.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/pipes/convert-message-table-titles-to-string.pipe.spec.ts
new file mode 100644
index 0000000..c13aa3b
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/pipes/convert-message-table-titles-to-string.pipe.spec.ts
@@ -0,0 +1,8 @@
+import { ConvertMessageTableTitlesToStringPipe } from './convert-message-table-titles-to-string.pipe';
+
+describe('ConvertMessageTableTitlesToStringPipe', () => {
+ it('create an instance', () => {
+ const pipe = new ConvertMessageTableTitlesToStringPipe();
+ expect(pipe).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/pipes/convert-message-table-titles-to-string.pipe.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/pipes/convert-message-table-titles-to-string.pipe.ts
new file mode 100644
index 0000000..d99bb05
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/pipes/convert-message-table-titles-to-string.pipe.ts
@@ -0,0 +1,27 @@
+import { Pipe, PipeTransform } from '@angular/core';
+const transformMatrix: any = {
+ sub_name: "SubMessage Name",
+ sub_description: "SubMessage Description",
+ sub_number: "SubMessage Number",
+ sub_txRate: "SubMessage Tx Rate",
+ name: "Message Name",
+ description: "Message Description",
+ interfaceMessageNumber: "Message Number",
+ interfaceMessagePeriodicity: "Periodicity",
+ interfaceMessageRate: "Tx Rate",
+ interfaceMessageWriteAccess: "Read/Write",
+ interfaceMessageType:"Type"
+}
+@Pipe({
+ name: 'convertMessageTableTitlesToString'
+})
+export class ConvertMessageTableTitlesToStringPipe implements PipeTransform {
+
+ transform(value: string, ...args: unknown[]): unknown {
+ if (transformMatrix[value] != null && transformMatrix[value] != undefined) {
+ return transformMatrix[value]
+ }
+ return value;
+ }
+
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/pipes/convert-sub-message-titles-to-string.pipe.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/pipes/convert-sub-message-titles-to-string.pipe.spec.ts
new file mode 100644
index 0000000..007b59f
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/pipes/convert-sub-message-titles-to-string.pipe.spec.ts
@@ -0,0 +1,8 @@
+import { ConvertSubMessageTitlesToStringPipe } from './convert-sub-message-titles-to-string.pipe';
+
+describe('ConvertSubMessageTitlesToStringPipe', () => {
+ it('create an instance', () => {
+ const pipe = new ConvertSubMessageTitlesToStringPipe();
+ expect(pipe).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/pipes/convert-sub-message-titles-to-string.pipe.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/pipes/convert-sub-message-titles-to-string.pipe.ts
new file mode 100644
index 0000000..0b8e8ea
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/pipes/convert-sub-message-titles-to-string.pipe.ts
@@ -0,0 +1,21 @@
+import { Pipe, PipeTransform } from '@angular/core';
+const transformMatrix: any = {
+ name: "SubMessage Name",
+ description: "SubMessage Description",
+ interfaceSubMessageNumber: "SubMessage Number",
+ interfaceMessageRate: "SubMessage Tx Rate",
+}
+@Pipe({
+ name: 'convertSubMessageTitlesToString'
+})
+export class ConvertSubMessageTitlesToStringPipe implements PipeTransform {
+
+ transform(value: string, ...args: unknown[]): unknown {
+ if (transformMatrix[value] != null && transformMatrix[value] != undefined) {
+ return transformMatrix[value]
+ }
+ return value;
+ }
+
+}
+
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/current-messages.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/current-messages.service.spec.ts
new file mode 100644
index 0000000..d9b5597
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/current-messages.service.spec.ts
@@ -0,0 +1,41 @@
+import { HttpClientModule } from '@angular/common/http';
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { apiURL } from 'src/environments/environment';
+import { message } from '../types/messages';
+
+import { CurrentMessagesService } from './current-messages.service';
+import { MessagesService } from './messages.service';
+import { UiService } from './ui.service';
+
+describe('CurrentMessagesService', () => {
+ let service: CurrentMessagesService;
+ let httpTestingController: HttpTestingController;
+ let uiService: UiService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports:[HttpClientTestingModule]
+ });
+ service = TestBed.inject(CurrentMessagesService);
+ httpTestingController = TestBed.inject(HttpTestingController);
+ uiService = TestBed.inject(UiService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should fetch filtered messages', fakeAsync(() => {
+ const testData: message[] = [];
+ service.filter = 'filter';
+ service.branch = '10';
+ service.messages.subscribe();
+ tick(500);
+ const req=httpTestingController.expectOne(apiURL + "/mim/branch/" + '10' + "/messages/filter/" + 'filter');
+ expect(req.request.method).toEqual("GET");
+ req.flush(testData);
+ httpTestingController.verify();
+ }));
+
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/current-messages.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/current-messages.service.ts
new file mode 100644
index 0000000..514d8a6
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/current-messages.service.ts
@@ -0,0 +1,94 @@
+import { Injectable } from '@angular/core';
+import { combineLatest } from 'rxjs';
+import { share, debounceTime, distinctUntilChanged, switchMap, repeatWhen, tap } from 'rxjs/operators';
+import { message } from '../types/messages';
+import { subMessage } from '../types/sub-messages';
+import { MessagesService } from './messages.service';
+import { SubMessagesService } from './sub-messages.service';
+import { UiService } from './ui.service';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class CurrentMessagesService {
+
+ private _messages = combineLatest(this.ui.filter,this.BranchId).pipe(
+ share(),
+ debounceTime(500),
+ distinctUntilChanged(),
+ switchMap(x => this.messageService.getFilteredMessages(x[0], x[1]).pipe(
+ repeatWhen(_ => this.ui.UpdateRequired),
+ share(),
+ ))
+ )
+
+ private _allMessages = combineLatest(this.BranchId).pipe(
+ share(),
+ switchMap(x => this.messageService.getFilteredMessages("", x[0]).pipe(
+ repeatWhen(_ => this.ui.UpdateRequired),
+ share(),
+ ))
+ )
+
+ constructor(private messageService: MessagesService, private subMessageService: SubMessagesService, private ui: UiService) { }
+
+ get messages() {
+ return this._messages;
+ }
+
+ get allMessages() {
+ return this._allMessages;
+ }
+
+ set filter(filter:string) {
+ this.ui.filterString = filter;
+ }
+
+ set branch(id: string) {
+ this.ui.BranchIdString = id;
+ }
+
+ get BranchId() {
+ return this.ui.BranchId;
+ }
+
+ partialUpdateSubMessage(body:Partial<subMessage>,messageId:string) {
+ return this.subMessageService.partialUpdateSubMessage(body, this.BranchId.getValue(), messageId).pipe(
+ tap(() => {
+ this.ui.updateMessages = true;
+ })
+ );
+ }
+
+ partialUpdateMessage(body: Partial<message>) {
+ return this.messageService.partialUpdateMessage(body, this.BranchId.getValue()).pipe(
+ tap(() => {
+ this.ui.updateMessages = true;
+ })
+ );
+ }
+
+ relateSubMessage(messageId:string,subMessageId:string) {
+ return this.subMessageService.relateSubMessage(this.BranchId.getValue(), messageId, subMessageId).pipe(
+ tap(() => {
+ this.ui.updateMessages = true;
+ })
+ );
+ }
+
+ createSubMessage(body:subMessage,messageId:string) {
+ return this.subMessageService.addSubMessage(body, this.BranchId.getValue(), messageId).pipe(
+ tap(() => {
+ this.ui.updateMessages = true;
+ })
+ );
+ }
+
+ createMessage(body:message) {
+ return this.messageService.addMessage(body,this.BranchId.getValue()).pipe(
+ tap(() => {
+ this.ui.updateMessages = true;
+ })
+ );
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/messages.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/messages.service.spec.ts
new file mode 100644
index 0000000..0c4ea69
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/messages.service.spec.ts
@@ -0,0 +1,19 @@
+import { HttpClientModule } from '@angular/common/http';
+import { TestBed } from '@angular/core/testing';
+
+import { MessagesService } from './messages.service';
+
+describe('MessagesService', () => {
+ let service: MessagesService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports:[HttpClientModule]
+ });
+ service = TestBed.inject(MessagesService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/messages.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/messages.service.ts
new file mode 100644
index 0000000..5fb4e59
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/messages.service.ts
@@ -0,0 +1,65 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs';
+import { apiURL } from 'src/environments/environment';
+import { MessageApiResponse } from '../types/ApiResponse';
+import { message } from '../types/messages';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class MessagesService {
+
+ constructor (private http: HttpClient) { }
+
+ /**
+ * Gets an array of messages based on a filter condition
+ * @param filter parameter to filter out messages that don't meet criteria
+ * @param branchId branch to look for messages on
+ * @returns Observable of an array of messages matching filter condition
+ */
+ getFilteredMessages(filter: string, branchId: string):Observable<message[]> {
+ return this.http.get<message[]>(apiURL + "/mim/branch/" + branchId + "/messages/filter/" + filter);
+ }
+
+ /**
+ * Adds a message to a branch
+ * @param body message to add
+ * @param branchId branch to look for messages on
+ * @returns api response of whether or not the insertion was successful
+ */
+ addMessage(body: message, branchId:string):Observable<MessageApiResponse> {
+ return this.http.post<MessageApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages", body);
+ }
+
+ /**
+ * Updates part of a message with new contents
+ * @param body message contents to add, requires id
+ * @param branchId branch to look for messages on
+ * @returns api response of whether or not the element was updated successfully
+ */
+ partialUpdateMessage(body: Partial<message>, branchId: string):Observable<MessageApiResponse> {
+ return this.http.patch<MessageApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages", body);
+ }
+
+ /**
+ * Removes a message from a branch
+ * @param branchId branch to look for contents on
+ * @param messageId id of message to delete
+ * @returns api response of whether or not the message was removed
+ */
+ removeMessage(branchId: string, messageId: string):Observable<MessageApiResponse> {
+ return this.http.delete<MessageApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/"+messageId);
+ }
+
+ /**
+ * Finds a specific message
+ * @param branchId branch to look for contents on
+ * @param messageId id of message to find
+ * @returns message contents, if found
+ */
+ getMessage(branchId: string, messageId: string):Observable<message> {
+ return this.http.get<message>(apiURL + "/mim/branch/" + branchId + "/messages/"+messageId);
+ }
+
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/sub-messages.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/sub-messages.service.spec.ts
new file mode 100644
index 0000000..741089d
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/sub-messages.service.spec.ts
@@ -0,0 +1,19 @@
+import { HttpClientModule } from '@angular/common/http';
+import { TestBed } from '@angular/core/testing';
+
+import { SubMessagesService } from './sub-messages.service';
+
+describe('SubMessagesService', () => {
+ let service: SubMessagesService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports:[HttpClientModule]
+ });
+ service = TestBed.inject(SubMessagesService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/sub-messages.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/sub-messages.service.ts
new file mode 100644
index 0000000..9a4e00d
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/sub-messages.service.ts
@@ -0,0 +1,34 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs';
+import { apiURL } from 'src/environments/environment';
+import { MessageApiResponse } from '../types/ApiResponse';
+import { subMessage } from '../types/sub-messages';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class SubMessagesService {
+
+ constructor (private http: HttpClient) { }
+
+ addSubMessage(body: subMessage, branchId: string, messageId: string):Observable<MessageApiResponse> {
+ return this.http.post<MessageApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages", body);
+ }
+
+ partialUpdateSubMessage(body: Partial<subMessage>, branchId: string, messageId: string):Observable<MessageApiResponse> {
+ return this.http.patch<MessageApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages", body);
+ }
+
+ relateSubMessage(branchId: string, messageId: string, subMessageId:string):Observable<MessageApiResponse> {
+ return this.http.patch<MessageApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/" + subMessageId, null);
+ }
+
+ unRelateSubMessage(branchId: string, messageId: string, subMessageId:string):Observable<MessageApiResponse> {
+ return this.http.delete<MessageApiResponse>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/" + subMessageId);
+ }
+
+ getSubMessage(branchId: string, messageId: string, subMessageId:string):Observable<subMessage> {
+ return this.http.get<subMessage>(apiURL + "/mim/branch/" + branchId + "/messages/" + messageId + "/submessages/" + subMessageId);
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/ui.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/ui.service.spec.ts
new file mode 100644
index 0000000..bcee990
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/ui.service.spec.ts
@@ -0,0 +1,47 @@
+import { TestBed } from '@angular/core/testing';
+import { TestScheduler } from 'rxjs/testing';
+
+import { UiService } from './ui.service';
+
+describe('UiService', () => {
+ let service: UiService;
+ let scheduler: TestScheduler;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({});
+ service = TestBed.inject(UiService);
+ });
+
+ beforeEach(() => scheduler = new TestScheduler((actual, expected) => {
+ expect(actual).toEqual(expected);
+ }));
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should set filter value', () => {
+ scheduler.run(() => {
+ const expectedfilterValues = { a: 'a', b: 'b' };
+ const expectedMarble = 'a'
+ scheduler.expectObservable(service.filter).toBe(expectedMarble, expectedfilterValues);
+ service.filterString = "a";
+ service.filterString = "a";
+ service.filterString = "b";
+ service.filterString = "a";
+ })
+ });
+
+ it('should set branch value', () => {
+ scheduler.run(() => {
+ const expectedfilterValues = { a: '1', b: '2' };
+ const expectedMarble = 'a'
+ scheduler.expectObservable(service.BranchId).toBe(expectedMarble, expectedfilterValues);
+ service.BranchIdString='1'
+ service.BranchIdString='1'
+ service.BranchIdString='2'
+ service.BranchIdString='1'
+ })
+ });
+
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/ui.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/ui.service.ts
new file mode 100644
index 0000000..2ee70a9
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/services/ui.service.ts
@@ -0,0 +1,40 @@
+import { Injectable } from '@angular/core';
+import { BehaviorSubject, Subject } from 'rxjs';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class UiService {
+
+ private _filter: BehaviorSubject<string> = new BehaviorSubject<string>("");
+
+ private _UpdateRequired: Subject<boolean> = new Subject<boolean>();
+ private _branchId: BehaviorSubject<string> = new BehaviorSubject<string>("0");
+ constructor() { }
+
+ get filter() {
+ return this._filter
+ }
+
+ set filterString(filter: string) {
+ if (filter !== this._filter.getValue()) {
+ this._filter.next(filter);
+ }
+ }
+
+ get UpdateRequired() {
+ return this._UpdateRequired;
+ }
+
+ set updateMessages(value: boolean) {
+ this._UpdateRequired.next(value);
+ }
+
+ get BranchId() {
+ return this._branchId;
+ }
+
+ set BranchIdString(value: string) {
+ this._branchId.next(value);
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/types/AddMessageDialog.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/types/AddMessageDialog.d.ts
new file mode 100644
index 0000000..3840ee0
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/types/AddMessageDialog.d.ts
@@ -0,0 +1,10 @@
+export interface AddMessageDialog{
+ id: string,
+ name: string,
+ description: string ,
+ interfaceMessageRate: string ,
+ interfaceMessagePeriodicity: string ,
+ interfaceMessageWriteAccess: string ,
+ interfaceMessageType: string ,
+ interfaceMessageNumber:string
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/types/AddSubMessageDialog.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/types/AddSubMessageDialog.d.ts
new file mode 100644
index 0000000..d09b9f4
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/types/AddSubMessageDialog.d.ts
@@ -0,0 +1,7 @@
+import { subMessage } from "./sub-messages";
+
+export interface AddSubMessageDialog{
+ id: string,
+ name:string,
+ subMessage: subMessage,
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/types/ApiResponse.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/types/ApiResponse.d.ts
new file mode 100644
index 0000000..5afd0a4
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/types/ApiResponse.d.ts
@@ -0,0 +1,21 @@
+/**
+ * Response the Platform Types API should return when doing a POST,PUT,PATCH, or DELETE to indicate success/status of API
+ */
+ export interface MessageApiResponse {
+ empty: boolean,
+ errorCount: number,
+ errors: boolean,
+ failed: boolean,
+ ids: string[],
+ infoCount: boolean,
+ numErrors: number,
+ numErrorsViaSearch: number,
+ numWarnings: number,
+ numWarningsViaSearch: number,
+ results: string[],
+ success: boolean,
+ tables: string[],
+ title: string,
+ txId: string,
+ warningCount: number
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/types/messages.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/types/messages.d.ts
new file mode 100644
index 0000000..d51da6a
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/types/messages.d.ts
@@ -0,0 +1,13 @@
+import { subMessage } from "./sub-messages";
+
+export interface message {
+ id: string,
+ name: string,
+ description: string ,
+ subMessages: Array<Required<subMessage>>,
+ interfaceMessageRate: string ,
+ interfaceMessagePeriodicity: string ,
+ interfaceMessageWriteAccess: boolean ,
+ interfaceMessageType: string ,
+ interfaceMessageNumber:string
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/types/sub-messages.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/types/sub-messages.d.ts
new file mode 100644
index 0000000..e967e95
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/message-interface/types/sub-messages.d.ts
@@ -0,0 +1,7 @@
+export interface subMessage {
+ id?: string,
+ name: string,
+ description: string,
+ interfaceMessageRate: string,
+ interfaceSubMessageNumber: string
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/messaging-routing.module.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/messaging-routing.module.ts
new file mode 100644
index 0000000..f5695c8
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/messaging-routing.module.ts
@@ -0,0 +1,17 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { MessagingComponent } from './messaging.component';
+
+const routes: Routes = [
+ { path: '', component: MessagingComponent },
+ { path: ':branchType/:branchId/messages/:messageId/:subMessageId/:name/elements', loadChildren: () => import('./message-element-interface/message-element-interface.module').then(m => m.MessageElementInterfaceModule) },
+ { path: ':branchType/:branchId/messages', loadChildren: () => import('./message-interface/message-interface.module').then(m => m.MessageInterfaceModule) },
+ { path: ':branchType/:branchId/types', loadChildren: () => import('./types-interface/types-interface.module').then(m => m.TypesInterfaceModule) },
+ { path: ':branchType/:branchId/types/:type', loadChildren: () => import('./types-interface/types-interface.module').then(m => m.TypesInterfaceModule) },
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule]
+})
+export class MessagingRoutingModule { }
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/messaging.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/messaging.component.html
new file mode 100644
index 0000000..b8f67b1
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/messaging.component.html
@@ -0,0 +1 @@
+<p>messaging works!</p>
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/messaging.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/messaging.component.sass
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/messaging.component.sass
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/messaging.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/messaging.component.spec.ts
new file mode 100644
index 0000000..0a04ea6
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/messaging.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { MessagingComponent } from './messaging.component';
+
+describe('MessagingComponent', () => {
+ let component: MessagingComponent;
+ let fixture: ComponentFixture<MessagingComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ MessagingComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(MessagingComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/messaging.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/messaging.component.ts
new file mode 100644
index 0000000..56f42f1
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/messaging.component.ts
@@ -0,0 +1,15 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-messaging',
+ templateUrl: './messaging.component.html',
+ styleUrls: ['./messaging.component.sass']
+})
+export class MessagingComponent implements OnInit {
+
+ constructor() { }
+
+ ngOnInit(): void {
+ }
+
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/messaging.module.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/messaging.module.ts
new file mode 100644
index 0000000..60e209a
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/messaging.module.ts
@@ -0,0 +1,17 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { MessagingRoutingModule } from './messaging-routing.module';
+import { MessagingComponent } from './messaging.component';
+import { PleSharedMaterialModule } from '../ple-shared-material/ple-shared-material.module';
+
+
+@NgModule({
+ declarations: [MessagingComponent],
+ imports: [
+ CommonModule,
+ PleSharedMaterialModule,
+ MessagingRoutingModule,
+ ]
+})
+export class MessagingModule { }
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/components/dialogs/column-preferences-dialog/column-preferences-dialog.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/components/dialogs/column-preferences-dialog/column-preferences-dialog.component.html
new file mode 100644
index 0000000..3322f45
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/components/dialogs/column-preferences-dialog/column-preferences-dialog.component.html
@@ -0,0 +1,69 @@
+<h1 mat-dialog-title>Settings</h1>
+<mat-dialog-content>
+ <mat-checkbox
+ [(ngModel)]="data.editable"
+ [disabled]="!(editability | async) || false"
+ color="primary"
+ >Edit Mode</mat-checkbox
+ >
+ <ng-container *ngIf="data.headersTableActive">
+ <h2>Column Preferences</h2>
+ <table class="mat-table mat-elevation-z8">
+ <tr class="mat-header-row">
+ <th class="mat-header-cell">
+ <mat-label>{{ data.headers1Label }}:</mat-label>
+ </th>
+ <th class="mat-header-cell">
+ <mat-label>{{ data.headers2Label }}:</mat-label>
+ </th>
+ </tr>
+ <tr class="mat-row">
+ <td class="mat-cell column-preferences-align-top">
+ <mat-selection-list
+ [(ngModel)]="data.allowedHeaders1"
+ color="primary"
+ >
+ <mat-list-option
+ *ngFor="let header of data.allHeaders1"
+ [value]="header"
+ >
+ {{ header | convertMessageInterfaceTitlesToString }}
+ </mat-list-option>
+ </mat-selection-list>
+ </td>
+ <td class="mat-cell column-preferences-align-top">
+ <mat-selection-list
+ [(ngModel)]="data.allowedHeaders2"
+ color="primary"
+ >
+ <mat-list-option
+ *ngFor="let header of data.allHeaders2"
+ [value]="header"
+ >
+ {{ header | convertMessageInterfaceTitlesToString }}
+ </mat-list-option>
+ </mat-selection-list>
+ </td>
+ </tr>
+ </table>
+ </ng-container>
+ <!-- <mat-selection-list [(ngModel)]="data.allowedStructureHeaders" color="primary">
+ <mat-label>Structure Headers:</mat-label>
+ <mat-list-option *ngFor="let header of data.allStructureHeaders" [value]="header">
+ {{header |convertMessageInterfaceTitlesToString}}
+ </mat-list-option>
+ </mat-selection-list>
+ <mat-selection-list [(ngModel)]="data.allowedElementHeaders" color="primary">
+ <mat-label>Element Headers:</mat-label>
+ <mat-list-option *ngFor="let header of data.allElementHeaders" [value]="header">
+ {{header |convertMessageInterfaceTitlesToString}}
+ </mat-list-option>
+ </mat-selection-list> -->
+</mat-dialog-content>
+<mat-dialog-actions align="end">
+ <button mat-button (click)="onNoClick()">Cancel</button>
+ <!-- [disabled]="data.allowedElementHeaders.length===0||data.allowedStructureHeaders.length===0" -->
+ <button mat-raised-button [mat-dialog-close]="data" color="primary">
+ Ok
+ </button>
+</mat-dialog-actions>
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/components/dialogs/column-preferences-dialog/column-preferences-dialog.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/components/dialogs/column-preferences-dialog/column-preferences-dialog.component.sass
new file mode 100644
index 0000000..8c124e3
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/components/dialogs/column-preferences-dialog/column-preferences-dialog.component.sass
@@ -0,0 +1,2 @@
+.column-preferences-align-top
+ vertical-align: top
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/components/dialogs/column-preferences-dialog/column-preferences-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/components/dialogs/column-preferences-dialog/column-preferences-dialog.component.spec.ts
new file mode 100644
index 0000000..5ea31d1
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/components/dialogs/column-preferences-dialog/column-preferences-dialog.component.spec.ts
@@ -0,0 +1,83 @@
+import { HttpClient } from '@angular/common/http';
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatCheckboxModule } from '@angular/material/checkbox';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatListModule } from '@angular/material/list';
+import { MatTableModule } from '@angular/material/table';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { apiURL } from 'src/environments/environment';
+import { ConvertMessageInterfaceTitlesToStringPipe } from '../../../pipes/convert-message-interface-titles-to-string.pipe';
+import { branchApplicability } from '../../../types/branch.applic';
+import { settingsDialogData } from '../../../types/settingsdialog';
+
+import { ColumnPreferencesDialogComponent } from './column-preferences-dialog.component';
+
+describe('ColumnPreferencesDialogComponent', () => {
+ let component: ColumnPreferencesDialogComponent;
+ let fixture: ComponentFixture<ColumnPreferencesDialogComponent>;
+ let dialogData:settingsDialogData= {
+ allowedHeaders1: ['s1','s2'],
+ allHeaders1: ['s1','s2','s3'],
+ allowedHeaders2: ['e1','e2'],
+ allHeaders2: ['e1', 'e2', 'e3'],
+ branchId: '10',
+ editable: false,
+ headers1Label: "Headers1 Label",
+ headers2Label: "Headers2 Label",
+ headersTableActive:true
+ };
+ let httpClient :HttpClient;
+ let httpTestingController: HttpTestingController;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports:[MatDialogModule, MatFormFieldModule,NoopAnimationsModule, MatListModule, FormsModule,MatButtonModule,MatTableModule,MatCheckboxModule, HttpClientTestingModule],
+ declarations: [ColumnPreferencesDialogComponent, ConvertMessageInterfaceTitlesToStringPipe],
+ providers: [{ provide: MatDialogRef, useValue: {} },
+ {provide:MAT_DIALOG_DATA,useValue:dialogData}]
+ })
+ .compileComponents();
+ httpClient = TestBed.inject(HttpClient);
+ httpTestingController = TestBed.inject(HttpTestingController);
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ColumnPreferencesDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should call the backend to get whether a branch is editable', () => {
+ let testData: branchApplicability = {
+ associatedArtifactId: '-1',
+ branch: {
+ id: '-1',
+ viewId: '-1',
+ idIntValue: -1,
+ name:''
+ },
+ editable: true,
+ features: [],
+ groups: [],
+ parentBranch: {
+ id: '-1',
+ viewId: '-1',
+ idIntValue: -1,
+ name:''
+ },
+ views:[]
+ }
+ const req = httpTestingController.expectOne(apiURL + '/orcs/applicui/branch/' + 10);
+ expect(req.request.method).toEqual('GET');
+ req.flush(testData);
+ httpTestingController.verify();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/components/dialogs/column-preferences-dialog/column-preferences-dialog.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/components/dialogs/column-preferences-dialog/column-preferences-dialog.component.ts
new file mode 100644
index 0000000..dcfd595
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/components/dialogs/column-preferences-dialog/column-preferences-dialog.component.ts
@@ -0,0 +1,32 @@
+import { Component, Inject, OnInit } from '@angular/core';
+import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { Observable } from 'rxjs';
+import { map } from 'rxjs/operators';
+import { EditAuthService } from '../../../services/edit-auth-service.service';
+import { settingsDialogData } from '../../../types/settingsdialog';
+
+@Component({
+ selector: 'app-column-preferences-dialog',
+ templateUrl: './column-preferences-dialog.component.html',
+ styleUrls: ['./column-preferences-dialog.component.sass']
+})
+export class ColumnPreferencesDialogComponent implements OnInit {
+ editability: Observable<boolean> = this.editAuthService.branchEditability.pipe(
+ map(x=>x?.editable)
+ )
+
+ constructor(public dialogRef: MatDialogRef<ColumnPreferencesDialogComponent>, @Inject(MAT_DIALOG_DATA) public data: settingsDialogData, private editAuthService: EditAuthService) {
+ this.editAuthService.BranchIdString = data.branchId;
+ }
+
+ ngOnInit(): void {
+ }
+
+ onNoClick() {
+ this.dialogRef.close();
+ }
+
+ log(value: any) {
+ console.log(value);
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/pipes/convert-message-interface-titles-to-string.pipe.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/pipes/convert-message-interface-titles-to-string.pipe.spec.ts
new file mode 100644
index 0000000..36ace50
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/pipes/convert-message-interface-titles-to-string.pipe.spec.ts
@@ -0,0 +1,8 @@
+import { ConvertMessageInterfaceTitlesToStringPipe } from './convert-message-interface-titles-to-string.pipe';
+
+describe('ConvertMessageInterfaceTitlesToStringPipe', () => {
+ it('create an instance', () => {
+ const pipe = new ConvertMessageInterfaceTitlesToStringPipe();
+ expect(pipe).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/pipes/convert-message-interface-titles-to-string.pipe.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/pipes/convert-message-interface-titles-to-string.pipe.ts
new file mode 100644
index 0000000..05748a6
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/pipes/convert-message-interface-titles-to-string.pipe.ts
@@ -0,0 +1,45 @@
+import { Pipe, PipeTransform } from '@angular/core';
+
+const transformMatrix:any = {
+ name: "Name",
+ interfaceStructureCategory: "Category",
+ TxRate: "Tx Rate",
+ interfaceMinSimultaneity: "Min Simult.",
+ interfaceMaxSimultaneity: "Max Simult.",
+ AttributeCount: "Attribute Count",
+ SizeInBytes: "Size(B)",
+ BytesPerSecondMinimum: "Min BPS",
+ BytesPerSecondMaximum: "Max BPS",
+ interfaceTaskFileType: "Task File Type",
+ description: "Description",
+ GenerationIndicator: "Indicator",
+ ElementName: "Element Name",
+ beginWord: "Begin Word",
+ endWord: "End Word",
+ BeginByte: "Begin Byte",
+ EndByte: "End Byte",
+ Sequence: "Seq",
+ Units: "Units",
+ MinValue: "Min",
+ MaxValue: "Max",
+ interfaceElementAlterable: "Alterable",
+ EnumsLiteralsDesc: "Enum Lit. Desc.",
+ notes: "Notes",
+ DefaultValue: "Default Value",
+ isArray: "Is An Array",
+ platformTypeName2: "Type"
+}
+
+@Pipe({
+ name: 'convertMessageInterfaceTitlesToString'
+})
+export class ConvertMessageInterfaceTitlesToStringPipe implements PipeTransform {
+
+ transform(value: string, ...args: unknown[]): string {
+ if (transformMatrix[value] != null && transformMatrix[value] != undefined) {
+ return transformMatrix[value]
+ }
+ return value;
+ }
+
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/services/edit-auth-service.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/services/edit-auth-service.service.spec.ts
new file mode 100644
index 0000000..47f54d5
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/services/edit-auth-service.service.spec.ts
@@ -0,0 +1,21 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { TestBed } from '@angular/core/testing';
+
+import { EditAuthService } from './edit-auth-service.service';
+
+describe('EditAuthServiceService', () => {
+ let service: EditAuthService;
+ let httpTestingController: HttpTestingController;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports:[HttpClientTestingModule]
+ });
+ service = TestBed.inject(EditAuthService);
+ httpTestingController = TestBed.inject(HttpTestingController);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/services/edit-auth-service.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/services/edit-auth-service.service.ts
new file mode 100644
index 0000000..931b85f
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/services/edit-auth-service.service.ts
@@ -0,0 +1,63 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { BehaviorSubject, iif, Observable, of } from 'rxjs';
+import { switchMap, share } from 'rxjs/operators';
+import { apiURL } from 'src/environments/environment';
+import { branchApplicability } from '../types/branch.applic';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class EditAuthService {
+ private _branchId: BehaviorSubject<string> = new BehaviorSubject<string>('0');
+ _branchEditability: Observable<branchApplicability> = this.BranchId.pipe(
+ switchMap((value: string) =>
+ iif(
+ () =>
+ value !== '' &&
+ value != '0' &&
+ value != '-1' &&
+ value !== undefined &&
+ value !== null,
+ this.getBranchInfo(value).pipe(share()),
+ of({
+ associatedArtifactId: '-1',
+ branch: {
+ id: '-1',
+ viewId: '-1',
+ idIntValue: -1,
+ name: '',
+ },
+ editable: false,
+ features: [],
+ groups: [],
+ parentBranch: {
+ id: '-1',
+ viewId: '-1',
+ idIntValue: -1,
+ name: '',
+ },
+ views: [],
+ })
+ )
+ )
+ );
+ constructor(private http: HttpClient) {}
+
+ private getBranchInfo(id: string | number) {
+ return this.http.get<branchApplicability>(
+ apiURL + '/orcs/applicui/branch/' + id
+ );
+ }
+
+ private get BranchId() {
+ return this._branchId;
+ }
+
+ set BranchIdString(value: string) {
+ this._branchId.next(value);
+ }
+ get branchEditability() {
+ return this._branchEditability;
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/services/ui/http-loading.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/services/ui/http-loading.service.spec.ts
new file mode 100644
index 0000000..61a9385
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/services/ui/http-loading.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { HttpLoadingService } from './http-loading.service';
+
+describe('HttpLoadingService', () => {
+ let service: HttpLoadingService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({});
+ service = TestBed.inject(HttpLoadingService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/services/ui/http-loading.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/services/ui/http-loading.service.ts
new file mode 100644
index 0000000..d59aa2e
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/services/ui/http-loading.service.ts
@@ -0,0 +1,20 @@
+import { Injectable } from '@angular/core';
+import { BehaviorSubject } from 'rxjs';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class HttpLoadingService {
+
+ private _isLoading: BehaviorSubject<String> = new BehaviorSubject<String>("true");
+ constructor () { }
+
+ get isLoading() {
+ return this._isLoading;
+ }
+
+ set loading(value: boolean) {
+ this._isLoading.next(value.toString());
+ }
+
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/shared-messaging.module.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/shared-messaging.module.ts
new file mode 100644
index 0000000..93cf8a9
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/shared-messaging.module.ts
@@ -0,0 +1,25 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { ColumnPreferencesDialogComponent } from './components/dialogs/column-preferences-dialog/column-preferences-dialog.component';
+import { FormsModule } from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatDialogModule } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatListModule } from '@angular/material/list';
+import {MatCheckboxModule} from '@angular/material/checkbox';
+import { ConvertMessageInterfaceTitlesToStringPipe } from './pipes/convert-message-interface-titles-to-string.pipe';
+
+@NgModule({
+ declarations: [ColumnPreferencesDialogComponent, ConvertMessageInterfaceTitlesToStringPipe],
+ imports: [
+ CommonModule,
+ MatDialogModule,
+ MatFormFieldModule,
+ MatListModule,
+ MatCheckboxModule,
+ FormsModule,
+ MatButtonModule,
+ ],
+ exports:[ConvertMessageInterfaceTitlesToStringPipe,ColumnPreferencesDialogComponent]
+})
+export class SharedMessagingModule {}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/types/branch.applic.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/types/branch.applic.d.ts
new file mode 100644
index 0000000..ecd5e6b
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/types/branch.applic.d.ts
@@ -0,0 +1,48 @@
+export interface branchApplicability{
+ associatedArtifactId: string,
+ branch: branch,
+ editable: boolean,
+ features: feature[],
+ groups: configurationGroup[],
+ parentBranch: branch,
+ views: view[],
+}
+
+interface branch{
+ id: string,
+ viewId: string,
+ idIntValue: number,
+ name: string,
+}
+
+interface view{
+ hasFeatureApplicabilities: boolean,
+ productApplicabilities?: string[],
+ id: string,
+ name:string
+}
+
+interface feature{
+ name: string,
+ description: string,
+ valueType: string,
+ valueStr?: string,
+ defaultValue: string,
+ productAppStr?: string,
+ values: string[],
+ productApplicabilities: string[],
+ multiValued: boolean;
+ id: string,
+ idIntValue?: number,
+ idString?: string,
+ type: null | undefined,
+ configurations:[{name:string, value:string}]
+}
+
+interface configurationGroup{
+ configurations:string[],
+ id: string,
+ name: string,
+ hasFeatureApplicabilities: boolean
+ productApplicabilities:string[]
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/types/branchstorage.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/types/branchstorage.d.ts
new file mode 100644
index 0000000..47cde89
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/types/branchstorage.d.ts
@@ -0,0 +1,7 @@
+export interface branchStorage{
+ mim: {
+ editMode: boolean,
+ StructureHeaders: string[],
+ ElementHeaders:string[]
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/types/settingsdialog.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/types/settingsdialog.d.ts
new file mode 100644
index 0000000..ec94783
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/shared/types/settingsdialog.d.ts
@@ -0,0 +1,12 @@
+export interface settingsDialogData{
+ branchId:string,
+ allowedHeaders1: string[],
+ allHeaders1: string[],
+ allHeaders2: string[],
+ allowedHeaders2: string[],
+ editable: boolean,
+ headers1Label: string,
+ headers2Label: string,
+ headersTableActive:boolean
+
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/edit-type-dialog/edit-type-dialog.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/edit-type-dialog/edit-type-dialog.component.html
new file mode 100644
index 0000000..1e0c5d7
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/edit-type-dialog/edit-type-dialog.component.html
@@ -0,0 +1,74 @@
+<ng-container *ngIf="!data.mode">
+ <h1 mat-dialog-title>Editing {{platform_type}}</h1>
+</ng-container>
+<ng-container *ngIf="data.mode">
+ <h1 mat-dialog-title>Creating New Type from {{platform_type}}</h1>
+</ng-container>
+<mat-dialog-content>
+ <mat-form-field>
+ <label>Platform Type</label>
+ <input matInput type="text" [(ngModel)]="data.type.name" #input required>
+ </mat-form-field>
+ <br>
+ <mat-form-field>
+ <label>Logical Type</label>
+ <input matInput type="text" [(ngModel)]="data.type.interfaceLogicalType" #input required>
+ </mat-form-field>
+ <br>
+ <!-- <mat-slide-toggle [(ngModel)]="data.type.interfacePlatform2sComplement" labelPosition='before' [style.fontSize.px]="18" color="primary" [disabled]="true">
+ Signed
+ </mat-slide-toggle> -->
+ <br>
+ <mat-form-field>
+ <label>Minimum Value</label>
+ <input matInput type="text" [(ngModel)]="data.type.interfacePlatformTypeMinval" #input required>
+ </mat-form-field>
+ <br>
+ <mat-form-field>
+ <label>Maximum Value</label>
+ <input matInput type="text" [(ngModel)]="data.type.interfacePlatformTypeMaxval" #input required>
+ </mat-form-field>
+ <br>
+ <mat-form-field>
+ <label>Byte Size</label>
+ <input matInput type="number" [(ngModel)]="byte_size" #input required>
+ </mat-form-field>
+ <br>
+ <mat-form-field>
+ <label>Bit Size</label>
+ <input matInput type="number" [(ngModel)]="data.type.interfacePlatformTypeBitSize" #input required>
+ </mat-form-field>
+ <br>
+ <mat-form-field>
+ <label>Default Value</label>
+ <input matInput type="text" [(ngModel)]="data.type.interfacePlatformTypeDefaultValue" #input required>
+ </mat-form-field>
+ <br>
+ <mat-form-field>
+ <label>MSB Value</label>
+ <input matInput type="number" [(ngModel)]="data.type.interfacePlatformTypeMsbValue" [ngModel]="getMSBValue()" #input required>
+ </mat-form-field>
+ <br>
+ <mat-form-field>
+ <label>Resolution</label>
+ <input matInput type="number" [(ngModel)]="data.type.interfacePlatformTypeBitsResolution" [ngModel]="getResolution()"#input required>
+ </mat-form-field>
+ <br>
+ <mat-form-field>
+ <label>Comp Rate</label>
+ <input matInput type="number" [(ngModel)]="data.type.interfacePlatformTypeCompRate" #input required>
+ </mat-form-field>
+ <br>
+ <mat-form-field>
+ <label>Analog Accuracy</label>
+ <input matInput [(ngModel)]="data.type.interfacePlatformTypeAnalogAccuracy" #input required>
+ </mat-form-field>
+</mat-dialog-content>
+<mat-dialog-actions align="end">
+ <button mat-button (click)="onNoClick()">
+ Cancel
+ </button>
+ <button mat-raised-button [mat-dialog-close]="data" color="primary" [disabled]="data.type.name.length===0||data.type.interfaceLogicalType.length===0">
+ Ok
+ </button>
+</mat-dialog-actions>
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/edit-type-dialog/edit-type-dialog.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/edit-type-dialog/edit-type-dialog.component.sass
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/edit-type-dialog/edit-type-dialog.component.sass
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/edit-type-dialog/edit-type-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/edit-type-dialog/edit-type-dialog.component.spec.ts
new file mode 100644
index 0000000..a532087
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/edit-type-dialog/edit-type-dialog.component.spec.ts
@@ -0,0 +1,82 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { HarnessLoader } from '@angular/cdk/testing';
+import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
+import { MatDialogHarness } from '@angular/material/dialog/testing';
+import { OverlayContainer } from '@angular/cdk/overlay';
+import { EditTypeDialogComponent } from './edit-type-dialog.component';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { FormsModule } from '@angular/forms';
+import { MatSlideToggleModule } from '@angular/material/slide-toggle';
+import { editPlatformTypeDialogData } from '../../types/editPlatformTypeDialogData';
+import { editPlatformTypeDialogDataMode } from '../../types/EditPlatformTypeDialogDataMode.enum';
+
+let loader: HarnessLoader;
+
+describe('EditTypeDialogComponent', () => {
+ let component: EditTypeDialogComponent;
+ let fixture: ComponentFixture<EditTypeDialogComponent>;
+ let overlayContainer: OverlayContainer;
+ let matDialogData: editPlatformTypeDialogData = {
+ mode: editPlatformTypeDialogDataMode.edit,
+ type: {
+ interfaceLogicalType: 'boolean',
+ interfacePlatform2sComplement: false,
+ interfacePlatformTypeAnalogAccuracy: 'N/A',
+ interfacePlatformTypeBitsResolution: 'N/A',
+ interfacePlatformTypeCompRate: '50Hz',
+ interfacePlatformTypeBitSize: '8',
+ interfacePlatformTypeDefaultValue: '0',
+ interfacePlatformTypeEnumLiteral: '',
+ interfacePlatformTypeMinval: '0',
+ interfacePlatformTypeMsbValue: '0',
+ interfacePlatformTypeMaxval: '1',
+ interfacePlatformTypeUnits: 'N/A',
+ interfacePlatformTypeValidRangeDescription: '',
+ name:'FACE Boolean'
+ }
+ }
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports:[MatDialogModule, MatFormFieldModule,MatInputModule,NoopAnimationsModule,FormsModule,MatSlideToggleModule],
+ declarations: [EditTypeDialogComponent],
+ providers: [
+ { provide: MatDialogRef, useValue: {} },
+ {
+ provide: MAT_DIALOG_DATA, useValue: matDialogData}
+ ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(EditTypeDialogComponent);
+ loader = TestbedHarnessEnvironment.loader(fixture);
+ overlayContainer = TestBed.inject(OverlayContainer);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ afterEach(async () => {
+ const dialogs = loader.getAllHarnesses(MatDialogHarness);
+ await Promise.all((await dialogs).map(async (d: MatDialogHarness) => await d.close()));
+ overlayContainer.ngOnDestroy();
+ })
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should create', async () => {
+ const dialogs = await loader.getAllHarnesses(MatDialogHarness);
+ dialogs.forEach((x) => {
+ console.log("Dialog: ")
+ console.log(x.getAriaLabel());
+ })
+ //const header = await dialog.getChildLoader('.mat-dialog-title');
+ //console.log(header);
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/edit-type-dialog/edit-type-dialog.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/edit-type-dialog/edit-type-dialog.component.ts
new file mode 100644
index 0000000..484a3d3
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/edit-type-dialog/edit-type-dialog.component.ts
@@ -0,0 +1,56 @@
+import { Component, Inject, OnInit } from '@angular/core';
+import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { editPlatformTypeDialogData } from '../../types/editPlatformTypeDialogData';
+
+@Component({
+ selector: 'app-edit-type-dialog',
+ templateUrl: './edit-type-dialog.component.html',
+ styleUrls: ['./edit-type-dialog.component.sass']
+})
+export class EditTypeDialogComponent implements OnInit {
+
+ platform_type: string =""
+ constructor(public dialogRef: MatDialogRef<EditTypeDialogComponent>, @Inject(MAT_DIALOG_DATA) public data: editPlatformTypeDialogData) {
+ this.platform_type = this.data.type.name;
+ }
+
+ ngOnInit(): void {
+ }
+
+ /**
+ * Calculates MSB value based on Bit Resolution, Byte Size and whether or not the type is signed/unsigned
+ * @returns @type {number} MSB Value
+ */
+ getMSBValue(): number{
+ return Number(this.data.type.interfacePlatformTypeBitsResolution)*(2^(((Number(this.data.type.interfacePlatformTypeBitSize)*8)-Number(this.data.type.interfacePlatform2sComplement))/2));
+ }
+
+ /**
+ * Calculates Resolution based on MSB value, Byte Size and whether or not the type is signed/unsigned
+ * @returns @type {number} Resolution
+ */
+ getResolution(): number{
+ return (Number(this.data.type.interfacePlatformTypeMsbValue) * 2) / (2 ^ ((Number(this.data.type.interfacePlatformTypeBitSize)*8) - Number(this.data.type.interfacePlatform2sComplement)));
+ }
+
+ /**
+ * Returns the bit size which is 8 * byte size
+ */
+ get byte_size() {
+ return Number(this.data.type.interfacePlatformTypeBitSize) /8;
+ }
+
+ /**
+ * Sets the byte size based on bit size /8
+ */
+ set byte_size(value: number) {
+ this.data.type.interfacePlatformTypeBitSize = String(value * 8);
+ }
+
+ /**
+ * Forcefully closes dialog without returning data
+ */
+ onNoClick(): void {
+ this.dialogRef.close();
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/new-type-dialog/new-type-dialog.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/new-type-dialog/new-type-dialog.component.html
new file mode 100644
index 0000000..6a95500
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/new-type-dialog/new-type-dialog.component.html
@@ -0,0 +1,69 @@
+<h1 mat-dialog-title>Create New Platform Type</h1>
+<mat-horizontal-stepper #stepper linear="true" class ="new-platform-type-stepper">
+ <mat-step label="Select a logical type" [completed]="type.length !== 0">
+ <mat-dialog-content>
+ <mat-form-field>
+ <mat-label>Logical Type</mat-label>
+ <mat-select [(ngModel)]="type" (selectionChange)="setType($event.value)">
+ <mat-option *ngFor="let logicaltype of (logicalTypes |async)" [value]="logicaltype.id" >
+ {{logicaltype.name |titlecase}}
+ </mat-option>
+ </mat-select>
+ </mat-form-field>
+ </mat-dialog-content>
+ <mat-dialog-actions align="end">
+ <button mat-button matStepperNext [disabled]="type.length === 0">Next</button>
+ </mat-dialog-actions>
+ </mat-step>
+ <mat-step label="Fill out type information" [completed]="isStep2Complete()">
+ <mat-dialog-content>
+ <mat-label class="mat-headline">Set fields for new type based on logical type {{(formInfo |async)?.name | titlecase}}</mat-label>
+ <br>
+ <ng-container *ngFor="let form of (formInfo | async)?.fields; index as i">
+ <ng-container *ngIf="form.editable">
+ <mat-form-field>
+ <mat-label>{{form.name}}</mat-label>
+ <input matInput type="text" [(ngModel)]="fields[i].value" #input [required]="form.required">
+ <ng-container *ngIf="form.defaultValue">
+ <mat-hint align="end">Default Value: {{form.defaultValue}}</mat-hint>
+ </ng-container>
+ </mat-form-field>
+ <br>
+ </ng-container>
+ <ng-container *ngIf="!form.editable">
+ {{setDefaultValue(form,i)}}
+ </ng-container>
+ </ng-container>
+ </mat-dialog-content>
+ <mat-dialog-actions align="end">
+ <button mat-button matStepperPrevious>Back</button>
+ <ng-container *ngIf="isStep2Complete()">
+ <button mat-raised-button matStepperNext [disabled]="!isStep2Complete()" [color]="isStep2Complete() ? 'primary': ''">Next</button>
+ </ng-container>
+ <ng-container *ngIf="!isStep2Complete()">
+ <button mat-button matStepperNext [disabled]="!isStep2Complete()" [color]="isStep2Complete() ? 'primary': ''">Next</button>
+ </ng-container>
+ </mat-dialog-actions>
+ </mat-step>
+ <mat-step label="Summary">
+ <mat-dialog-content>
+ <p class="mat-headline">
+ A new platform type of type {{(formInfo |async)?.name | titlecase}} will be created with the following properties:
+ </p>
+ <br>
+ <br>
+ <ng-container *ngFor="let field of fields">
+ <ng-container *ngIf="field.value!==''">
+ <mat-label class="mat-title">{{field.name}} : {{field.value}}</mat-label>
+ <br>
+ </ng-container>
+ </ng-container>
+ </mat-dialog-content>
+ <mat-dialog-actions align="end">
+ <button mat-button matStepperPrevious>Back</button>
+ <button mat-raised-button color="primary" [mat-dialog-close]="fields">
+ Ok
+ </button>
+ </mat-dialog-actions>
+ </mat-step>
+</mat-horizontal-stepper>
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/new-type-dialog/new-type-dialog.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/new-type-dialog/new-type-dialog.component.sass
new file mode 100644
index 0000000..4527cbe
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/new-type-dialog/new-type-dialog.component.sass
@@ -0,0 +1,14 @@
+::host
+ width: 100%
+ height: 100%
+body
+ width: 100%
+ height: 100%
+.mat-form-field
+ width: 100%
+.mat-horizontal-stepper-content
+ height: 100%
+ width: 100%
+.mat-horizontal-content-container
+ height: 100%
+ width: 100%
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/new-type-dialog/new-type-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/new-type-dialog/new-type-dialog.component.spec.ts
new file mode 100644
index 0000000..53b33f0
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/new-type-dialog/new-type-dialog.component.spec.ts
@@ -0,0 +1,45 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatDialogModule, MatDialogRef } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatSelectModule } from '@angular/material/select';
+import { MatStepperModule } from '@angular/material/stepper';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { of } from 'rxjs';
+import { CurrentTypesService } from '../../services/current-types.service';
+
+import { NewTypeDialogComponent } from './new-type-dialog.component';
+
+describe('NewTypeDialogComponent', () => {
+ let component: NewTypeDialogComponent;
+ let fixture: ComponentFixture<NewTypeDialogComponent>;
+ let typesService: Partial<CurrentTypesService> = {
+ logicalTypes:of([{id: '0',
+ name: 'name',
+ idString: '0',
+ idIntValue: 0
+ }])
+ }
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports:[MatDialogModule, MatStepperModule,NoopAnimationsModule,MatSelectModule,FormsModule,MatFormFieldModule,MatInputModule,MatButtonModule],
+ declarations: [NewTypeDialogComponent],
+ providers: [{ provide: MatDialogRef, useValue: {} },
+ {provide:CurrentTypesService, useValue:typesService}]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(NewTypeDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/new-type-dialog/new-type-dialog.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/new-type-dialog/new-type-dialog.component.ts
new file mode 100644
index 0000000..3e93e74
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/new-type-dialog/new-type-dialog.component.ts
@@ -0,0 +1,104 @@
+import { Component, OnInit } from '@angular/core';
+import { MatDialogRef } from '@angular/material/dialog';
+import { MatSelectChange } from '@angular/material/select';
+import { from, Observable, Subject } from 'rxjs';
+import {
+ concatMap,
+ debounceTime,
+ distinctUntilChanged,
+ share,
+ switchMap,
+ tap,
+} from 'rxjs/operators';
+import { CurrentTypesService } from '../../services/current-types.service';
+import { logicalType, logicalTypeFieldInfo, logicalTypeFormDetail } from '../../types/logicaltype';
+import { logicalTypefieldValue } from '../../types/newTypeDialogDialogData';
+import { PlatformType } from '../../types/platformType';
+
+@Component({
+ selector: 'app-new-type-dialog',
+ templateUrl: './new-type-dialog.component.html',
+ styleUrls: ['./new-type-dialog.component.sass'],
+})
+export class NewTypeDialogComponent implements OnInit {
+ returnObj: Partial<PlatformType> = {};
+ type: string = "";
+ private _typeName:string =""
+ private _typeSubject: Subject<string> = new Subject();
+ logicalTypes: Observable<logicalType[]> = this.typesService.logicalTypes;
+ fields: logicalTypefieldValue[] = [];
+ formInfo = this._typeSubject.pipe(
+ debounceTime(500),
+ distinctUntilChanged(),
+ switchMap((x) =>
+ this.typesService.getLogicalTypeFormDetail(x).pipe(share())
+ ),
+ share()
+ );
+ formDetail!: logicalTypeFormDetail;
+ private _fieldObs = this.formInfo.pipe(
+ tap((c) => {
+ this.fields = [];
+ this._typeName = c.name;
+ }),
+ concatMap((a) => from(a.fields)),
+ tap((x) => {
+ this.fields.push({
+ name: x.attributeType,
+ value: '',
+ });
+ }),
+ debounceTime(200),
+ tap((z) => {
+ this.fields.push({
+ name: "interfaceLogicalType",
+ value: this._typeName
+ })
+ })
+ );
+ constructor(
+ public dialogRef: MatDialogRef<NewTypeDialogComponent>,
+ private typesService: CurrentTypesService
+ ) {
+ this._fieldObs.subscribe();
+ this.formInfo.subscribe((value) => {
+ this.formDetail = value;
+ })
+ }
+
+ ngOnInit(): void { }
+ /**
+ * sets the current type to query
+ * @param id id of type
+ */
+ setType(id: string) {
+ this._typeSubject.next(id);
+ }
+ /**
+ * Validates the second step of the form
+ * @returns true if all required fields have a filled in value
+ */
+ isStep2Complete() {
+ let result: boolean = true;
+ if (this.formDetail !== undefined) {
+ this.formDetail.fields.forEach((value, index) => {
+ if (value.required && this.fields[index].value.length === 0) {
+ if (value.editable) {
+ result = false;
+ }
+ if (!value.editable && this.fields[index].value !== value.defaultValue) {
+ result = false;
+ }
+ }
+ })
+ }
+ return result;
+ }
+ setDefaultValue(form: logicalTypeFieldInfo, index: number) {
+ if (this.fields[index].name === form.attributeType) {
+ if (this.fields[index].value === null || this.fields[index].value === undefined || this.fields[index].value === "") {
+ this.fields[index].value = form.defaultValue;
+ }
+ }
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/platform-type-card/platform-type-card.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/platform-type-card/platform-type-card.component.html
new file mode 100644
index 0000000..13e4c1e
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/platform-type-card/platform-type-card.component.html
@@ -0,0 +1,44 @@
+<mat-card class="mat-elevation-z8">
+ <div mat-card-header>
+ <div mat-card-title>
+ {{typeData.name}}
+ </div>
+ <div mat-card-subtitle>
+ {{typeData.interfaceLogicalType}}
+ </div>
+ </div>
+ <div mat-card-content>
+ <div *ngIf="typeData.interfacePlatformTypeMinval">
+ Minimum Value:<br> {{typeData.interfacePlatformTypeMinval}}
+ </div>
+ <div *ngIf="typeData.interfacePlatformTypeMaxval">
+ Maximum Value:<br> {{typeData.interfacePlatformTypeMaxval}}
+ </div>
+ <div *ngIf="typeData.interfacePlatformTypeBitSize">
+ Bit Size: {{typeData.interfacePlatformTypeBitSize}}
+ </div>
+ <div *ngIf="typeData.interfacePlatformTypeDefaultValue">
+ Default Value: {{typeData.interfacePlatformTypeDefaultValue}}
+ </div>
+ <div *ngIf="typeData.interfacePlatformTypeMsbValue">
+ MSB Value: {{typeData.interfacePlatformTypeMsbValue}}
+ </div>
+ <div *ngIf="typeData.interfacePlatformTypeBitsResolution">
+ Resolution: {{typeData.interfacePlatformTypeBitsResolution}}
+ </div>
+ <div *ngIf="typeData.interfacePlatformTypeCompRate">
+ Comp Rate: {{typeData.interfacePlatformTypeCompRate}}
+ </div>
+ <div *ngIf="typeData.interfacePlatformTypeAnalogAccuracy">
+ Analog Accuracy: {{typeData.interfacePlatformTypeAnalogAccuracy}}
+ </div>
+ </div>
+ <div mat-card-actions>
+ <button mat-stroked-button (click)="openDialog(edit)">
+ Edit
+ </button>
+ <button mat-stroked-button (click)="openDialog(copy)">
+ Create New Type From Base
+ </button>
+ </div>
+</mat-card>
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/platform-type-card/platform-type-card.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/platform-type-card/platform-type-card.component.sass
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/platform-type-card/platform-type-card.component.sass
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/platform-type-card/platform-type-card.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/platform-type-card/platform-type-card.component.spec.ts
new file mode 100644
index 0000000..4ae87c4
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/platform-type-card/platform-type-card.component.spec.ts
@@ -0,0 +1,140 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { HarnessLoader } from '@angular/cdk/testing';
+import { MatCardHarness } from '@angular/material/card/testing';
+import { MatButtonHarness } from '@angular/material/button/testing';
+import { MatDialogHarness } from '@angular/material/dialog/testing';
+import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
+import { MatDialog, MatDialogModule } from '@angular/material/dialog';
+import { By } from '@angular/platform-browser';
+
+import { PlatformTypeCardComponent } from './platform-type-card.component';
+import { MatCardModule } from '@angular/material/card';
+import { MatButtonModule } from '@angular/material/button';
+import { Observable, of } from 'rxjs';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatSlideToggleModule } from '@angular/material/slide-toggle';
+import { FormsModule } from '@angular/forms';
+import { MatInputModule } from '@angular/material/input';
+import { EditTypeDialogComponent } from '../edit-type-dialog/edit-type-dialog.component';
+import { editPlatformTypeDialogDataMode } from '../../types/EditPlatformTypeDialogDataMode.enum';
+import { CurrentTypesService } from '../../services/current-types.service';
+
+let loader: HarnessLoader;
+
+describe('PlatformTypeCardComponent', () => {
+ let component: PlatformTypeCardComponent;
+ let fixture: ComponentFixture<PlatformTypeCardComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports:[MatCardModule, MatDialogModule,MatButtonModule, MatFormFieldModule,MatSlideToggleModule,FormsModule,MatInputModule, NoopAnimationsModule],
+ declarations: [PlatformTypeCardComponent, EditTypeDialogComponent],
+ providers: [{
+ provide: CurrentTypesService, useValue: {
+ partialUpdate: {
+ empty: false,
+ errorCount: 0,
+ errors: false,
+ failed: false,
+ ids: ["1"],
+ infoCount: false,
+ numErrors: 0,
+ numErrorsViaSearch: 0,
+ numWarnings: 0,
+ numWarningsViaSearch: 0,
+ results: [],
+ success: true,
+ tables: [],
+ title: "Patching 1",
+ txId: "2",
+ warningCount:0
+ }
+ }}
+ // {
+ // provide: MatDialog, useValue: {
+ // open() {
+ // },
+ // afterClosed(): Observable<object> {
+ // return of({
+ // data: {
+ // mode: Math.random()<0.5? 'copy':'edit'
+ // }
+ // })
+ // }
+ // }
+ // },
+ ],
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(PlatformTypeCardComponent);
+ loader = TestbedHarnessEnvironment.loader(fixture);
+ component = fixture.componentInstance;
+ const expectedData={
+ id: "0",
+ name: "Random Boolean",
+ interfaceLogicalType: "Boolean",
+ interfacePlatformTypeMinval: "0",
+ interfacePlatformTypeMaxval: "1",
+ interfacePlatformTypeBitSize: "8",
+ interfacePlatformTypeDefaultValue: "0",
+ interfacePlatformTypeMsbValue: "0",
+ interfacePlatformTypeBitsResolution: "0",
+ interfacePlatformTypeCompRate: "0",
+ interfacePlatformTypeAnalogAccuracy: "0",
+ interfacePlatform2sComplement: false,
+ interfacePlatformTypeEnumLiteral: "A string",
+ interfacePlatformTypeUnits: "N/A",
+ interfacePlatformTypeValidRangeDescription:"N/A"
+ }
+ component.typeData = expectedData;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should create a header of class mat-card-header-text with text of Random Boolean',async () => {
+ fixture.detectChanges();
+ const card = await loader.getHarness(MatCardHarness);
+ expect(await card.getTitleText()).toEqual("Random Boolean");
+ });
+ it('should create a subtitle with text of Boolean',async () => {
+ fixture.detectChanges();
+ const card = await loader.getHarness(MatCardHarness);
+ expect(await card.getSubtitleText()).toEqual("Boolean");
+ });
+
+ it('should contain text that has minimum value, maximum value, byte size, default value, msb value, resolution, comp rate, analog accuracy, edit and Create New Type From Base',async () => {
+ fixture.detectChanges();
+ const card = await loader.getHarness(MatCardHarness);
+ expect(await card.getText()).toEqual("Random Boolean Boolean Minimum Value: 0 Maximum Value: 1 Bit Size: 8 Default Value: 0 MSB Value: 0 Resolution: 0 Comp Rate: 0 Analog Accuracy: 0 Edit Create New Type From Base");
+ });
+
+ it('should call openDialog()', async () => {
+ const openDialog = spyOn(component, 'openDialog').and.callThrough();
+ const buttons = await (await loader.getHarness(MatCardHarness)).getAllHarnesses(MatButtonHarness);
+ buttons.forEach(async (b) => {
+ await b.click();
+ let text: editPlatformTypeDialogDataMode;
+ if (await b.getText() === 'Create New Type From Base') {
+ text = editPlatformTypeDialogDataMode.copy;
+ } else {
+ text = editPlatformTypeDialogDataMode.edit;
+ }
+ await expect(openDialog).toHaveBeenCalledWith(text);
+ });
+ expect(component).toBeTruthy();
+ })
+ //Don't know how to do this test yet
+ // it('should open a dialog subscription',async () => {
+ // fixture.detectChanges();
+ // component.openDialog('edit');
+ // component.dialog.
+ // });
+
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/platform-type-card/platform-type-card.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/platform-type-card/platform-type-card.component.ts
new file mode 100644
index 0000000..38bbce5
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/platform-type-card/platform-type-card.component.ts
@@ -0,0 +1,68 @@
+import { Component, Input, OnInit } from '@angular/core';
+import { MatDialog } from '@angular/material/dialog';
+import { defer, Observable, of } from 'rxjs';
+import { switchMap } from 'rxjs/operators';
+import { CurrentTypesService } from '../../services/current-types.service';
+import { TypesApiResponse } from '../../types/ApiResponse';
+import { editPlatformTypeDialogData } from '../../types/editPlatformTypeDialogData';
+import { editPlatformTypeDialogDataMode } from '../../types/EditPlatformTypeDialogDataMode.enum';
+import { PlatformType } from '../../types/platformType';
+import { EditTypeDialogComponent } from '../edit-type-dialog/edit-type-dialog.component';
+
+@Component({
+ selector: 'ple-messaging-types-platform-type-card',
+ templateUrl: './platform-type-card.component.html',
+ styleUrls: ['./platform-type-card.component.sass']
+})
+export class PlatformTypeCardComponent implements OnInit {
+
+ @Input() typeData!: PlatformType;
+ edit: editPlatformTypeDialogDataMode = editPlatformTypeDialogDataMode.edit;
+ copy: editPlatformTypeDialogDataMode = editPlatformTypeDialogDataMode.copy;
+ constructor(public dialog: MatDialog, private typesService: CurrentTypesService) { }
+
+ ngOnInit(): void {
+ }
+
+ /**
+ * Opens a Dialog for either editing or creating a new platform type based on the current platform type
+ * @param value Whether the dialog should be in edit or copy mode (see @enum {editPlatformTypeDialogDataMode})
+ */
+ openDialog(value:editPlatformTypeDialogDataMode) {
+ let dialogData: editPlatformTypeDialogData = {
+ mode: value,
+ type:this.typeData
+ }
+ const copy = JSON.parse(JSON.stringify(this.typeData));
+ const dialogRef=this.dialog.open(EditTypeDialogComponent, {
+ data: dialogData,
+ })
+ dialogRef.afterClosed()
+ .pipe(
+ switchMap(
+ x => defer(
+ () => x.mode ? this.typesService.createType(x.type) : this.getEditObservable(copy,x)
+ )
+ )
+ ).subscribe((result) => {})
+ }
+
+ /**
+ * Gets an observable for updating the attributes of a platform type
+ * @param copy Initial values of the platform type PRIOR to the dialog being opened
+ * @param result Changed values of the platform type + mode AFTER the dialog is closed
+ * @returns @type {Observable<TypesApiResponse>} observable containing results (see @type {TypesApiResponse} and @type {Observable})
+ */
+ getEditObservable(copy: PlatformType, result: editPlatformTypeDialogData): Observable<TypesApiResponse> {
+ let newType: any = new Object();
+ Object.keys(copy).forEach((value) => {
+ if (copy[value as keyof PlatformType] !== result.type[value as keyof PlatformType]) {
+ newType[value as keyof PlatformType] = result.type[value as keyof PlatformType];
+ }
+ })
+ newType["id"] = copy["id"]
+
+
+ return this.typesService.partialUpdate(newType);
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/type-grid/type-grid.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/type-grid/type-grid.component.html
new file mode 100644
index 0000000..501131b
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/type-grid/type-grid.component.html
@@ -0,0 +1,13 @@
+<button mat-fab (click)="openNewTypeDialog()" class="new-platform-type-button" color="primary">+</button>
+<mat-form-field class="ple-messaging-type-grid-filter">
+ <mat-label>Filter Types</mat-label>
+ <input matInput type="text" (keyup)="applyFilter($event)" #input [value]="filterValue">
+ <mat-hint>Enter text to filter Types.
+ </mat-hint>
+</mat-form-field>
+<div class="ple-messaging-type-grid">
+ <ng-container *ngFor="let card of (filteredData | async); let i=index;">
+ <ple-messaging-types-platform-type-card [typeData]="card" [attr.width]="getWidthString()" [style.margin]="getMarginString()" class="typeElement">
+ </ple-messaging-types-platform-type-card>
+ </ng-container>
+</div>
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/type-grid/type-grid.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/type-grid/type-grid.component.sass
new file mode 100644
index 0000000..8f5d206
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/type-grid/type-grid.component.sass
@@ -0,0 +1,23 @@
+.ple-messaging-type-grid-filter
+ width: 100%
+ padding:
+ left: 1%
+ bottom: 1%
+.ple-messaging-type-grid-list
+ height: 100%
+.new-platform-type-button
+ z-index: 10
+ position: fixed
+ bottom: 3%
+ right: 2%
+.ple-messaging-type-grid
+ display: flex
+ justify-content: space-between
+ flex-wrap: wrap
+ align-items: baseline
+ @media screen and ( max-width: 600px )
+ display: block
+.typeElement
+ flex:1 1
+
+
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/type-grid/type-grid.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/type-grid/type-grid.component.spec.ts
new file mode 100644
index 0000000..275eda2
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/type-grid/type-grid.component.spec.ts
@@ -0,0 +1,103 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { HarnessLoader } from '@angular/cdk/testing';
+import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
+import { FormsModule } from '@angular/forms';
+import { MatCardModule } from '@angular/material/card';
+import { MatDialogModule } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatGridListModule } from '@angular/material/grid-list';
+import { MatInputModule } from '@angular/material/input';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { MatFormFieldHarness } from '@angular/material/form-field/testing';
+import { MatInputHarness } from '@angular/material/input/testing';
+import { PlatformTypeCardComponent } from '../platform-type-card/platform-type-card.component';
+
+import { TypeGridComponent } from './type-grid.component';
+import { LayoutModule } from '@angular/cdk/layout';
+import { PlatformType } from '../../types/platformType';
+import { CurrentTypesService } from '../../services/current-types.service';
+import { BehaviorSubject, Observable, of } from 'rxjs';
+import { PlMessagingTypesUIService } from '../../services/pl-messaging-types-ui.service';
+
+let loader: HarnessLoader;
+
+describe('TypeGridComponent', () => {
+ let component: TypeGridComponent;
+ let fixture: ComponentFixture<TypeGridComponent>;
+ let typeData: Observable<PlatformType[]> = of(
+ [
+ {
+ interfaceLogicalType: "boolean",
+ interfacePlatform2sComplement: false,
+ interfacePlatformTypeAnalogAccuracy: "Hello",
+ interfacePlatformTypeBitsResolution: "1",
+ interfacePlatformTypeBitSize: "8",
+ interfacePlatformTypeCompRate: "1",
+ interfacePlatformTypeDefaultValue: "1",
+ interfacePlatformTypeEnumLiteral: "Enum Lit.",
+ interfacePlatformTypeMaxval: "1",
+ interfacePlatformTypeMinval: "0",
+ interfacePlatformTypeMsbValue: "1",
+ interfacePlatformTypeUnits: "N/A",
+ interfacePlatformTypeValidRangeDescription: "Description",
+ name:"boolean"
+ },
+ {
+ interfaceLogicalType: "integer",
+ interfacePlatform2sComplement: false,
+ interfacePlatformTypeAnalogAccuracy: "Hello",
+ interfacePlatformTypeBitsResolution: "1",
+ interfacePlatformTypeBitSize: "8",
+ interfacePlatformTypeCompRate: "1",
+ interfacePlatformTypeDefaultValue: "1",
+ interfacePlatformTypeEnumLiteral: "Enum Lit.",
+ interfacePlatformTypeMaxval: "1",
+ interfacePlatformTypeMinval: "0",
+ interfacePlatformTypeMsbValue: "1",
+ interfacePlatformTypeUnits: "N/A",
+ interfacePlatformTypeValidRangeDescription: "Description",
+ name:"integer"
+ }
+ ]
+ );
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports:[MatCardModule,MatFormFieldModule,NoopAnimationsModule,MatInputModule,MatGridListModule, MatDialogModule, FormsModule, LayoutModule],
+ declarations: [PlatformTypeCardComponent, TypeGridComponent],
+ providers: [{
+ provide: CurrentTypesService, useValue:
+ {
+ typeData:typeData
+ }
+ }, {
+ provide: PlMessagingTypesUIService, useValue: {
+ filterString: '',
+ columnCountNumber: 1,
+ columnCount:new BehaviorSubject(1),
+ singleLineAdjustment:of(0)
+ }}]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(TypeGridComponent);
+ component = fixture.componentInstance;
+ loader = TestbedHarnessEnvironment.loader(fixture);
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should filter', async () => {
+ let form = await loader.getHarness(MatFormFieldHarness);
+ let input = await form.getControl(MatInputHarness);
+ await input?.setValue("boolean");
+ expect(component.filterValue).toEqual("boolean");
+ //@todo replace with a check to see that the filter value is set
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/type-grid/type-grid.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/type-grid/type-grid.component.ts
new file mode 100644
index 0000000..e9d350f
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/components/type-grid/type-grid.component.ts
@@ -0,0 +1,119 @@
+import { BreakpointObserver, Breakpoints, BreakpointState } from '@angular/cdk/layout';
+import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
+import { MatDialog } from '@angular/material/dialog';
+import { BehaviorSubject, combineLatest } from 'rxjs';
+import { CurrentTypesService } from '../../services/current-types.service';
+import { PlMessagingTypesUIService } from '../../services/pl-messaging-types-ui.service';
+import { PlatformType } from '../../types/platformType';
+import { NewTypeDialogComponent } from '../new-type-dialog/new-type-dialog.component';
+
+@Component({
+ selector: 'ple-messaging-types-type-grid',
+ templateUrl: './type-grid.component.html',
+ styleUrls: ['./type-grid.component.sass']
+})
+export class TypeGridComponent implements OnInit, OnChanges {
+ @Input() filterValue: string = "";
+ columnCount= this.uiService.columnCount;
+ gutterSize: string = "";
+ filteredData = this.typesService.typeData;
+ rowHeight: string = "";
+
+ constructor(private breakpointObserver: BreakpointObserver, private typesService: CurrentTypesService, private uiService: PlMessagingTypesUIService,public dialog: MatDialog) {
+ this.uiService.filterString = this.filterValue;
+ const breakpoint =this.breakpointObserver.observe(
+ [
+ Breakpoints.XSmall,
+ Breakpoints.Small,
+ Breakpoints.Medium,
+ Breakpoints.Large,
+ Breakpoints.XLarge,
+ Breakpoints.Web,
+ ]
+ )
+ const combined = combineLatest([breakpoint, this.uiService.singleLineAdjustment]).subscribe((result) => {
+ this.updateColumnsCount(result);
+ })
+ }
+
+ ngOnChanges(changes: SimpleChanges): void {
+ this.uiService.filterString = this.filterValue;
+ }
+
+ ngOnInit(): void {
+ }
+
+ /**
+ * Adjusts the layout of the page based on CDK Layout Observer
+ * @param state Array containing the state of the page (i.e. what breakpoints) and whether or not to adjust the layout due to being on a single line
+ */
+ updateColumnsCount(state: [BreakpointState,number]) {
+ if (state[0].matches) {
+ if (state[0].breakpoints[Breakpoints.XSmall]) {
+ this.uiService.columnCountNumber = 1;
+ this.gutterSize = "16";
+ }
+ if (state[0].breakpoints[Breakpoints.Small]) {
+ this.uiService.columnCountNumber = 2;
+ this.gutterSize = "16";
+ }
+ if (state[0].breakpoints[Breakpoints.Medium]) {
+ this.rowHeight = 45 + state[1] + "%";
+ //this.rowHeight="30%"
+ this.uiService.columnCountNumber = 3;
+ this.gutterSize = "24";
+ }
+ if (state[0].breakpoints[Breakpoints.Large] && !state[0].breakpoints[Breakpoints.Medium]) {
+ this.rowHeight = 45+state[1]+"%"; //37
+ this.uiService.columnCountNumber = 4;
+ this.gutterSize = "24";
+ }
+ if (state[0].breakpoints[Breakpoints.XLarge] && !state[0].breakpoints[Breakpoints.Large]) {
+ //this.rowHeight = "45%";
+ this.rowHeight = 45+state[1]+"%";
+ this.uiService.columnCountNumber = 5;
+ this.gutterSize = "24";
+ }
+ if (state[0].breakpoints[Breakpoints.Web]) {
+ this.rowHeight = 45+state[1]+"%";
+ this.uiService.columnCountNumber = 5;
+ this.gutterSize = "24";
+ }
+ }
+ }
+
+ /**
+ * Sets the filter value so the API can update the data on the page.
+ * @param event Event containing user input from the filter
+ */
+ applyFilter(event: Event) {
+ this.filterValue = (event.target as HTMLInputElement).value.trim().toLowerCase();
+ this.uiService.filterString = this.filterValue;
+ }
+
+ openNewTypeDialog() {
+ const dialogRef = this.dialog.open(NewTypeDialogComponent, {
+ minHeight: "70vh",
+ minWidth:"80vw"
+ });
+ dialogRef.afterClosed().subscribe((result) => {
+ this.mapTo(result);
+ })
+ }
+
+ mapTo(results: Array<{ name: string, value: string | boolean }>) {
+ let resultingObj: Partial<PlatformType> = {};
+ results.forEach((el) => {
+ let name = el.name.charAt(0).toLowerCase() + el.name.slice(1);
+ (resultingObj as any)[name]=el.value
+ })
+ this.typesService.createType(resultingObj).subscribe();
+ }
+
+ getWidthString() {
+ return 100 / this.columnCount.getValue()+"% -"+this.gutterSize+'px';
+ }
+ getMarginString() {
+ return this.gutterSize+'px'
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/services/current-types.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/services/current-types.service.spec.ts
new file mode 100644
index 0000000..251d34d
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/services/current-types.service.spec.ts
@@ -0,0 +1,153 @@
+import { HttpClientModule } from '@angular/common/http';
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
+import { fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { apiURL } from 'src/environments/environment';
+import { TypesApiResponse } from '../types/ApiResponse';
+import { logicalType, logicalTypeFormDetail } from '../types/logicaltype';
+import { PlatformType } from '../types/platformType.d';
+
+import { CurrentTypesService } from './current-types.service';
+import { PlMessagingTypesUIService } from './pl-messaging-types-ui.service';
+
+class PlatformTypeInstance implements PlatformType{
+ id?: string | undefined ='';
+ interfaceLogicalType: string='';
+ interfacePlatform2sComplement: boolean=false;
+ interfacePlatformTypeAnalogAccuracy: string | null='';
+ interfacePlatformTypeBitsResolution: string | null='';
+ interfacePlatformTypeBitSize: string | null='';
+ interfacePlatformTypeCompRate: string | null='';
+ interfacePlatformTypeDefaultValue: string | null='';
+ interfacePlatformTypeEnumLiteral: string | null='';
+ interfacePlatformTypeMaxval: string | null='';
+ interfacePlatformTypeMinval: string | null='';
+ interfacePlatformTypeMsbValue: string | null='';
+ interfacePlatformTypeUnits: string | null='';
+ interfacePlatformTypeValidRangeDescription: string | null='';
+ name: string='';
+ constructor () {}
+
+}
+
+describe('CurrentTypesServiceService', () => {
+ let service: CurrentTypesService;
+ let uiService: PlMessagingTypesUIService;
+ let httpTestingController:HttpTestingController
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports:[HttpClientTestingModule]
+ });
+ service = TestBed.inject(CurrentTypesService);
+ uiService = TestBed.inject(PlMessagingTypesUIService);
+ httpTestingController = TestBed.inject(HttpTestingController);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+
+ it('should fetch data from backend', fakeAsync(() => {
+ let testData: PlatformType[] = []
+ uiService.BranchIdString = "10";
+ service.typeData.subscribe();
+ uiService.filterString = "A filter";
+ tick(500);
+ const req = httpTestingController.expectOne(apiURL + "/mim/branch/" + "10" + "/types/filter/" + "A filter");
+ expect(req.request.method).toEqual('GET');
+ req.flush(testData);
+ httpTestingController.verify();
+ }));
+
+ it('should set singleLineAdjustment to 0', fakeAsync(() => {
+ let testData: PlatformType[] = [new PlatformTypeInstance(), new PlatformTypeInstance(), new PlatformTypeInstance()]
+ uiService.columnCountNumber = 2;
+ uiService.BranchIdString = "10";
+ service.typeData.subscribe();
+ uiService.filterString = "A filter";
+ tick(500);
+ const req = httpTestingController.expectOne(apiURL + "/mim/branch/" + "10" + "/types/filter/" + "A filter");
+ //expect(req.request.method).toEqual('GET');
+ req?.flush(testData);
+ httpTestingController.verify();
+ expect(uiService.singleLineAdjustment.getValue()).toEqual(0);
+ }));
+
+ it('should send a patch request', () => {
+ uiService.BranchIdString = "10";
+ service.partialUpdate({}).subscribe();
+ let testData: TypesApiResponse = {
+ empty: false,
+ errorCount: 0,
+ errors: false,
+ failed: false,
+ ids: [],
+ infoCount: false,
+ numErrors: 0,
+ numErrorsViaSearch: 0,
+ numWarnings: 0,
+ numWarningsViaSearch: 0,
+ results: [],
+ success: true,
+ tables: [],
+ title: '',
+ txId: '',
+ warningCount: 0
+ };
+ const req = httpTestingController.expectOne(apiURL + "/mim/branch/" + "10" + "/types");
+ expect(req.request.method).toEqual('PATCH');
+ req.flush(testData);
+ httpTestingController.verify();
+ });
+
+ it('should send a post request', () => {
+ uiService.BranchIdString = "10";
+ service.createType({}).subscribe();
+ let testData: TypesApiResponse = {
+ empty: false,
+ errorCount: 0,
+ errors: false,
+ failed: false,
+ ids: [],
+ infoCount: false,
+ numErrors: 0,
+ numErrorsViaSearch: 0,
+ numWarnings: 0,
+ numWarningsViaSearch: 0,
+ results: [],
+ success: true,
+ tables: [],
+ title: '',
+ txId: '',
+ warningCount: 0
+ };
+ const req = httpTestingController.expectOne(apiURL + "/mim/branch/" + "10" + "/types");
+ expect(req.request.method).toEqual('POST');
+ req.flush(testData);
+ httpTestingController.verify();
+ });
+
+ it('should fetch logical types', () => {
+ service.logicalTypes.subscribe();
+ let testData: logicalType[] = [];
+ const req = httpTestingController.expectOne(apiURL + "/mim/logicalType");
+ expect(req.request.method).toEqual('GET');
+ req.flush(testData);
+ httpTestingController.verify();
+ });
+
+ it('should fetch a specific logical type', () => {
+ service.getLogicalTypeFormDetail("1").subscribe();
+ let testData: logicalTypeFormDetail = {
+ fields: [],
+ id: '1',
+ name: 'name',
+ idString: '1',
+ idIntValue:1
+ }
+ const req = httpTestingController.expectOne(apiURL + "/mim/logicalType/1");
+ expect(req.request.method).toEqual('GET');
+ req.flush(testData);
+ httpTestingController.verify();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/services/current-types.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/services/current-types.service.ts
new file mode 100644
index 0000000..d530b9e
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/services/current-types.service.ts
@@ -0,0 +1,74 @@
+import { Injectable } from '@angular/core';
+import { iif, Observable } from 'rxjs';
+import { debounceTime, distinctUntilChanged, repeatWhen, share, switchMap, tap } from 'rxjs/operators';
+import { PlMessagingTypesUIService } from './pl-messaging-types-ui.service';
+import { TypesService } from './types.service';
+import { PlatformType } from '../types/platformType'
+import { TypesApiResponse } from '../types/ApiResponse';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class CurrentTypesService {
+
+ private _typeData: Observable<PlatformType[]> = this.uiService.filter.pipe(
+ share(),
+ debounceTime(500),
+ distinctUntilChanged(),
+ switchMap(x => this.typesService.getFilteredTypes(x,this.uiService.BranchId.getValue()).pipe(
+ repeatWhen(_ => this.uiService.typeUpdateRequired),
+ share(),
+ tap((y) => {
+ this.uiService.updateTypes = false;
+ if (y.length <= this.uiService.columnCount.getValue()) {
+ this.uiService.singleLineAdjustmentNumber = 30;
+ } else {
+ this.uiService.singleLineAdjustmentNumber = 0;
+ }
+ })
+ )),
+ )
+
+ constructor(private typesService: TypesService, private uiService: PlMessagingTypesUIService) { }
+
+ /**
+ * Returns a list of platform types based on current branch and filter conditions(debounced).
+ * Sets the "single line adjustment" which is used to offset platform type cards in the grid when there is only one line of platform types
+ * Also updates when insertions are done via API.
+ * @returns @type {Observable<PlatformType[]>} list of platform types
+ */
+ get typeData() {
+ return this._typeData;
+ }
+
+ /**
+ * Updates the attributes of a platform type using the platform types PATCH API and current branch, id is required
+ * @param body @type {Partial<PlatformType>} attributes to update + id of platform type
+ * @returns @type {Observable<TypesApiResponse>} observable containing results (see @type {TypesApiResponse} and @type {Observable})
+ */
+ partialUpdate(body: Partial<PlatformType>) {
+ return this.typesService.partialUpdateTypes(body, this.uiService.BranchId.getValue());
+ }
+
+ /**
+ * Creates a new platform type using the platform types POST API, current branch,but without the id,idIntValue, and idString present
+ * @param body @type {PlatformType} platform type to create
+ * @returns @type {Observable<TypesApiResponse>} observable containing results (see @type {TypesApiResponse} and @type {Observable})
+ */
+ createType(body: PlatformType|Partial<PlatformType>) {
+ delete body.id;
+ return this.typesService.createType(body, this.uiService.BranchId.getValue()).pipe(
+ tap((response) => {
+ this.uiService.updateTypes = true;
+ })
+ );
+ }
+
+ get logicalTypes() {
+ return this.typesService.logicalTypes;
+ }
+
+ getLogicalTypeFormDetail(id: string) {
+ return this.typesService.getLogicalTypeFormDetail(id);
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/services/pl-messaging-types-ui.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/services/pl-messaging-types-ui.service.spec.ts
new file mode 100644
index 0000000..1a273af
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/services/pl-messaging-types-ui.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { PlMessagingTypesUIService } from './pl-messaging-types-ui.service';
+
+describe('PlMessagingTypesUIService', () => {
+ let service: PlMessagingTypesUIService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({});
+ service = TestBed.inject(PlMessagingTypesUIService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/services/pl-messaging-types-ui.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/services/pl-messaging-types-ui.service.ts
new file mode 100644
index 0000000..0fc4177
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/services/pl-messaging-types-ui.service.ts
@@ -0,0 +1,62 @@
+import { Injectable } from '@angular/core';
+import { BehaviorSubject, Subject } from 'rxjs';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class PlMessagingTypesUIService {
+
+ private _filter: BehaviorSubject<string> = new BehaviorSubject<string>("");
+ private _singleLineAdjustment: BehaviorSubject<number> = new BehaviorSubject<number>(0);
+
+ private _columnCount: BehaviorSubject<number> = new BehaviorSubject<number>(0);
+ private _typesUpdateRequired: Subject<boolean> = new Subject<boolean>();
+ private _branchId: BehaviorSubject<string> = new BehaviorSubject<string>("0");
+ constructor() { }
+
+ get filter() {
+ return this._filter
+ }
+
+ set filterString(filter: string) {
+ if (filter !== this._filter.getValue()) {
+ this._filter.next(filter);
+ }
+ }
+
+ get singleLineAdjustment() {
+ return this._singleLineAdjustment;
+ }
+
+ set singleLineAdjustmentNumber(value: number) {
+ if (value !== this._singleLineAdjustment.getValue()) {
+ this._singleLineAdjustment.next(value);
+ }
+ }
+
+ get columnCount() {
+ return this._columnCount;
+ }
+
+ set columnCountNumber(value: number) {
+ if (value !== this._columnCount.getValue()) {
+ this._columnCount.next(value);
+ }
+ }
+
+ get typeUpdateRequired() {
+ return this._typesUpdateRequired;
+ }
+
+ set updateTypes(value: boolean) {
+ this._typesUpdateRequired.next(value);
+ }
+
+ get BranchId() {
+ return this._branchId;
+ }
+
+ set BranchIdString(value: string) {
+ this._branchId.next(value);
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/services/types.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/services/types.service.spec.ts
new file mode 100644
index 0000000..3bd3970
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/services/types.service.spec.ts
@@ -0,0 +1,19 @@
+import { HttpClientModule } from '@angular/common/http';
+import { TestBed } from '@angular/core/testing';
+
+import { TypesService } from './types.service';
+
+describe('TypesService', () => {
+ let service: TypesService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports:[HttpClientModule]
+ });
+ service = TestBed.inject(TypesService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/services/types.service.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/services/types.service.ts
new file mode 100644
index 0000000..c74eb9e
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/services/types.service.ts
@@ -0,0 +1,52 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs';
+import { apiURL } from 'src/environments/environment';
+import { TypesApiResponse } from '../types/ApiResponse';
+import { logicalType, logicalTypeFormDetail } from '../types/logicaltype';
+import { PlatformType } from '../types/platformType';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class TypesService {
+
+ constructor(private http: HttpClient) { }
+
+ /**
+ * Gets a list of Platform Types based on a filter condition using the platform types filter GET API
+ * @param filter @type {string} filter conditions for finding the correct platform types
+ * @param branchId @type {string} branch to fetch from
+ * @returns @type {Observable<PlatformType[]>} Observable of array of platform types matching filter conditions (see @type {PlatformType} and @type {Observable})
+ */
+ getFilteredTypes(filter: string, branchId: string): Observable<PlatformType[]> {
+ return this.http.get<PlatformType[]>(apiURL + "/mim/branch/" + branchId + "/types/filter/" + filter);
+ }
+
+ /**
+ * Updates the attributes of a platform type using the platform types PATCH API, id is required
+ * @param body @type {Partial<PlatformType>} attributes to update + id of platform type
+ * @param branchId @type {string} branch to fetch from
+ * @returns @type {Observable<TypesApiResponse>} observable containing results (see @type {TypesApiResponse} and @type {Observable})
+ */
+ partialUpdateTypes(body: Partial<PlatformType>, branchId: string) :Observable<TypesApiResponse> {
+ return this.http.patch<TypesApiResponse>(apiURL + "/mim/branch/" + branchId + "/types", body);
+ }
+
+ /**
+ * Creates a new PlatformType using the platform types POST API
+ * @param body @type {PlatformType} platform type to create
+ * @param branchId @type {string} branch to fetch from
+ * @returns @type {Observable<TypesApiResponse>} observable containing results (see @type {TypesApiResponse} and @type {Observable})
+ */
+ createType(body: PlatformType|Partial<PlatformType>, branchId: string): Observable<TypesApiResponse> {
+ return this.http.post<TypesApiResponse>(apiURL + "/mim/branch/" + branchId + "/types", body);
+ }
+
+ get logicalTypes() {
+ return this.http.get<logicalType[]>(apiURL + "/mim/logicalType");
+ }
+ getLogicalTypeFormDetail(id:string) {
+ return this.http.get<logicalTypeFormDetail>(apiURL + "/mim/logicalType/" + id);
+ }
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types-interface-routing.module.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types-interface-routing.module.ts
new file mode 100644
index 0000000..8681243
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types-interface-routing.module.ts
@@ -0,0 +1,13 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { TypesInterfaceComponent } from './types-interface.component';
+
+const routes: Routes = [
+ { path: '', component: TypesInterfaceComponent },
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule]
+})
+export class TypesInterfaceRoutingModule { }
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types-interface.component.html b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types-interface.component.html
new file mode 100644
index 0000000..cbf0809
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types-interface.component.html
@@ -0,0 +1 @@
+<ple-messaging-types-type-grid [filterValue]="filterValue"></ple-messaging-types-type-grid>
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types-interface.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types-interface.component.sass
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types-interface.component.sass
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types-interface.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types-interface.component.spec.ts
new file mode 100644
index 0000000..b8e1eac
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types-interface.component.spec.ts
@@ -0,0 +1,77 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatCardModule } from '@angular/material/card';
+import { MatDialogModule } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatGridListModule } from '@angular/material/grid-list';
+import { MatInputModule } from '@angular/material/input';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { RouterTestingModule } from '@angular/router/testing';
+import { of } from 'rxjs';
+import { PlatformTypeCardComponent } from './components/platform-type-card/platform-type-card.component';
+import { TypeGridComponent } from './components/type-grid/type-grid.component';
+import { CurrentTypesService } from './services/current-types.service';
+
+import { TypesInterfaceComponent } from './types-interface.component';
+
+describe('TypesInterfaceComponent', () => {
+ let component: TypesInterfaceComponent;
+ let fixture: ComponentFixture<TypesInterfaceComponent>;
+ let typesService: Partial<CurrentTypesService> = {
+ typeData:of(
+ [
+ {
+ interfaceLogicalType: "boolean",
+ interfacePlatform2sComplement: false,
+ interfacePlatformTypeAnalogAccuracy: "Hello",
+ interfacePlatformTypeBitsResolution: "1",
+ interfacePlatformTypeBitSize: "8",
+ interfacePlatformTypeCompRate: "1",
+ interfacePlatformTypeDefaultValue: "1",
+ interfacePlatformTypeEnumLiteral: "Enum Lit.",
+ interfacePlatformTypeMaxval: "1",
+ interfacePlatformTypeMinval: "0",
+ interfacePlatformTypeMsbValue: "1",
+ interfacePlatformTypeUnits: "N/A",
+ interfacePlatformTypeValidRangeDescription: "Description",
+ name:"boolean"
+ },
+ {
+ interfaceLogicalType: "integer",
+ interfacePlatform2sComplement: false,
+ interfacePlatformTypeAnalogAccuracy: "Hello",
+ interfacePlatformTypeBitsResolution: "1",
+ interfacePlatformTypeBitSize: "8",
+ interfacePlatformTypeCompRate: "1",
+ interfacePlatformTypeDefaultValue: "1",
+ interfacePlatformTypeEnumLiteral: "Enum Lit.",
+ interfacePlatformTypeMaxval: "1",
+ interfacePlatformTypeMinval: "0",
+ interfacePlatformTypeMsbValue: "1",
+ interfacePlatformTypeUnits: "N/A",
+ interfacePlatformTypeValidRangeDescription: "Description",
+ name:"integer"
+ }
+ ]
+ )
+ }
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports:[MatCardModule,MatFormFieldModule,NoopAnimationsModule,MatInputModule,MatGridListModule, MatDialogModule, FormsModule, RouterTestingModule],
+ declarations: [TypesInterfaceComponent, TypeGridComponent, PlatformTypeCardComponent],
+ providers:[{provide: CurrentTypesService, useValue:typesService}]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(TypesInterfaceComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types-interface.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types-interface.component.ts
new file mode 100644
index 0000000..22ced80
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types-interface.component.ts
@@ -0,0 +1,21 @@
+import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { PlMessagingTypesUIService } from './services/pl-messaging-types-ui.service';
+
+@Component({
+ selector: 'app-types-interface',
+ templateUrl: './types-interface.component.html',
+ styleUrls: ['./types-interface.component.sass']
+})
+export class TypesInterfaceComponent implements OnInit {
+ filterValue: string = "";
+ constructor(private route: ActivatedRoute, private uiService: PlMessagingTypesUIService) { }
+
+ ngOnInit(): void {
+ this.route.paramMap.subscribe((values) => {
+ this.filterValue = values.get('type')?.trim().toLowerCase() || '';
+ this.uiService.BranchIdString = values.get('branchId') || '';
+ })
+ }
+
+}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types-interface.module.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types-interface.module.ts
new file mode 100644
index 0000000..bd6837f
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types-interface.module.ts
@@ -0,0 +1,42 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { TypesInterfaceRoutingModule } from './types-interface-routing.module';
+import { TypesInterfaceComponent } from './types-interface.component';
+import { PlatformTypeCardComponent } from './components/platform-type-card/platform-type-card.component';
+
+import { MatCardModule } from '@angular/material/card';
+import { MatGridListModule } from '@angular/material/grid-list';
+import { PleSharedMaterialModule } from '../../ple-shared-material/ple-shared-material.module';
+import { LayoutModule } from '@angular/cdk/layout';
+import { TypeGridComponent } from './components/type-grid/type-grid.component';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatDialogModule } from '@angular/material/dialog';
+import { MatSlideToggleModule } from '@angular/material/slide-toggle';
+import { FormsModule } from '@angular/forms';
+import { EditTypeDialogComponent } from './components/edit-type-dialog/edit-type-dialog.component';
+import { NewTypeDialogComponent } from './components/new-type-dialog/new-type-dialog.component';
+import { MatSelectModule } from '@angular/material/select';
+import {MatStepperModule} from '@angular/material/stepper';
+
+
+@NgModule({
+ declarations: [TypesInterfaceComponent, PlatformTypeCardComponent, TypeGridComponent, EditTypeDialogComponent, NewTypeDialogComponent],
+ imports: [
+ CommonModule,
+ MatCardModule,
+ MatGridListModule,
+ LayoutModule,
+ MatFormFieldModule,
+ MatInputModule,
+ MatDialogModule,
+ MatSelectModule,
+ MatStepperModule,
+ FormsModule,
+ MatSlideToggleModule,
+ PleSharedMaterialModule,
+ TypesInterfaceRoutingModule
+ ]
+})
+export class TypesInterfaceModule { }
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types/ApiResponse.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types/ApiResponse.d.ts
new file mode 100644
index 0000000..d6dad78
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types/ApiResponse.d.ts
@@ -0,0 +1,21 @@
+/**
+ * Response the Platform Types API should return when doing a POST,PUT,PATCH, or DELETE to indicate success/status of API
+ */
+export interface TypesApiResponse {
+ empty: boolean,
+ errorCount: number,
+ errors: boolean,
+ failed: boolean,
+ ids: string[],
+ infoCount: boolean,
+ numErrors: number,
+ numErrorsViaSearch: number,
+ numWarnings: number,
+ numWarningsViaSearch: number,
+ results: string[],
+ success: boolean,
+ tables: string[],
+ title: string,
+ txId: string,
+ warningCount: number
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types/BranchTypes.enum.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types/BranchTypes.enum.d.ts
new file mode 100644
index 0000000..22a29ac
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types/BranchTypes.enum.d.ts
@@ -0,0 +1,12 @@
+/**
+ * Enum mapping from several works over to baseline/working for api and browser url purposes
+ */
+export enum BranchType {
+ baseline = "baseline",
+ BaseLine = "baseline",
+ Baseline = "baseline",
+ productline = "baseline",
+ ProductLine = "baseline",
+ Productline = "baseline",
+ working = "working"
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types/EditPlatformTypeDialogDataMode.enum.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types/EditPlatformTypeDialogDataMode.enum.d.ts
new file mode 100644
index 0000000..edc0dba
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types/EditPlatformTypeDialogDataMode.enum.d.ts
@@ -0,0 +1,9 @@
+/**
+ * Enum representing whether or not the "Edit Dialog" should be in edit mode or create mode
+ * edit = 0
+ * copy = 1
+ */
+export const enum editPlatformTypeDialogDataMode {
+ edit,
+ copy
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types/editPlatformTypeDialogData.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types/editPlatformTypeDialogData.d.ts
new file mode 100644
index 0000000..0f4af02
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types/editPlatformTypeDialogData.d.ts
@@ -0,0 +1,10 @@
+import { editPlatformTypeDialogDataMode } from "./EditPlatformTypeDialogDataMode.enum";
+import { PlatformType } from "./platformType";
+
+/**
+ * Container containing info on whether or not the Edit Dialog should open in create/edit mode and what data to pre populate the fields with.
+ */
+export interface editPlatformTypeDialogData {
+ mode: editPlatformTypeDialogDataMode,
+ type: PlatformType
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types/logicaltype.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types/logicaltype.d.ts
new file mode 100644
index 0000000..82ffaf9
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types/logicaltype.d.ts
@@ -0,0 +1,17 @@
+export interface logicalType {
+ id: string,
+ name: string,
+ idString: string,
+ idIntValue:number
+}
+
+export interface logicalTypeFormDetail extends logicalType {
+ fields:logicalTypeFieldInfo[]
+}
+interface logicalTypeFieldInfo {
+ attributeType: string,
+ editable: boolean,
+ name:string,
+ required: boolean,
+ defaultValue:string
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types/newTypeDialogDialogData.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types/newTypeDialogDialogData.d.ts
new file mode 100644
index 0000000..0e1ccb5
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types/newTypeDialogDialogData.d.ts
@@ -0,0 +1,7 @@
+export interface newTypeDialogData {
+ fields:logicalTypefieldValue[]
+}
+export interface logicalTypefieldValue {
+ name: string,
+ value:string
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types/platformType.d.ts b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types/platformType.d.ts
new file mode 100644
index 0000000..1e5294f
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/messaging/types-interface/types/platformType.d.ts
@@ -0,0 +1,21 @@
+/**
+ * Platform Type as defined by the API, ids are required when fetching or updating a platform type
+ */
+export interface PlatformType {
+ id?: string,
+ interfaceLogicalType: string,
+ interfacePlatform2sComplement: boolean,
+ interfacePlatformTypeAnalogAccuracy: string | null,
+ interfacePlatformTypeBitsResolution: string | null,
+ interfacePlatformTypeBitSize: string | null,
+ interfacePlatformTypeCompRate: string | null,
+ interfacePlatformTypeDefaultValue: string | null,
+ interfacePlatformTypeEnumLiteral: string | null,
+ interfacePlatformTypeMaxval: string | null,
+ interfacePlatformTypeMinval: string | null,
+ interfacePlatformTypeMsbValue: string | null,
+ interfacePlatformTypeUnits: string | null,
+ interfacePlatformTypeValidRangeDescription: string | null,
+ name: string
+
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/action-drop-down/action-drop-down.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/action-drop-down/action-drop-down.component.spec.ts
index 40ce5d7..d2941b4 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/action-drop-down/action-drop-down.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/action-drop-down/action-drop-down.component.spec.ts
@@ -1,4 +1,5 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MatButtonModule } from '@angular/material/button';
import { MatDialog } from '@angular/material/dialog';
import { Router, ActivatedRoute } from '@angular/router';
import { of } from 'rxjs';
@@ -15,6 +16,7 @@
beforeEach(async () => {
await TestBed.configureTestingModule({
+ imports:[MatButtonModule],
declarations: [ActionDropDownComponent],
providers: [
{ provide: MatDialog, useValue: {} },
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/add-configuration-dialog/add-configuration-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/add-configuration-dialog/add-configuration-dialog.component.spec.ts
index 912656b..9417e1a 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/add-configuration-dialog/add-configuration-dialog.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/add-configuration-dialog/add-configuration-dialog.component.spec.ts
@@ -1,6 +1,14 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { FormsModule } from '@angular/forms';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatListModule } from '@angular/material/list';
+import { MatSelectModule } from '@angular/material/select';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { PlConfigBranchService } from '../../services/pl-config-branch-service.service';
+import { PlConfigCurrentBranchService } from '../../services/pl-config-current-branch.service';
+import { PlConfigTypesService } from '../../services/pl-config-types.service';
import { AddConfigurationDialogComponent } from './add-configuration-dialog.component';
@@ -9,12 +17,16 @@
let fixture: ComponentFixture<AddConfigurationDialogComponent>;
beforeEach(async () => {
- const branchService = jasmine.createSpyObj('PlConfigBranchService', ['getBranchApplicability',]);
+ const branchService = jasmine.createSpyObj('PlConfigBranchService', ['getBranchApplicability',]);
+ const currentBranchService = jasmine.createSpyObj('PlConfigCurrentBranchService', [], ['cfgGroups']);
+ const typesService = jasmine.createSpyObj('PlConfigTypesService', [], ['productApplicabilityTypes']);
await TestBed.configureTestingModule({
+ imports:[MatFormFieldModule,MatListModule,MatDialogModule,MatInputModule, MatSelectModule, NoopAnimationsModule,FormsModule],
declarations: [AddConfigurationDialogComponent],
- providers:[{
- provide: PlConfigBranchService, useValue: branchService
- },
+ providers: [
+ { provide: PlConfigBranchService, useValue: branchService },
+ { provide: PlConfigCurrentBranchService, useValue: currentBranchService },
+ { provide: PlConfigTypesService, useValue: typesService },
{ provide: MatDialogRef, useValue: {} },
{
provide: MAT_DIALOG_DATA, useValue: {
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/add-configuration-group-dialog/add-configuration-group-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/add-configuration-group-dialog/add-configuration-group-dialog.component.spec.ts
index 2ab41d4..2c1cff1 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/add-configuration-group-dialog/add-configuration-group-dialog.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/add-configuration-group-dialog/add-configuration-group-dialog.component.spec.ts
@@ -1,4 +1,9 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { AddConfigurationGroupDialogComponent } from './add-configuration-group-dialog.component';
@@ -8,7 +13,15 @@
beforeEach(async () => {
await TestBed.configureTestingModule({
- declarations: [ AddConfigurationGroupDialogComponent ]
+ imports:[MatDialogModule,MatInputModule,FormsModule,MatFormFieldModule,NoopAnimationsModule],
+ declarations: [AddConfigurationGroupDialogComponent],
+ providers: [
+ { provide: MatDialogRef, useValue: {} },
+ {
+ provide: MAT_DIALOG_DATA, useValue: {
+ title: ''
+ }}
+ ]
})
.compileComponents();
});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/add-feature-dialog/add-feature-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/add-feature-dialog/add-feature-dialog.component.spec.ts
index c37c515..7d7ae75 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/add-feature-dialog/add-feature-dialog.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/add-feature-dialog/add-feature-dialog.component.spec.ts
@@ -1,6 +1,14 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { FormsModule } from '@angular/forms';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatListModule } from '@angular/material/list';
+import { MatSelectModule } from '@angular/material/select';
+import { MatSlideToggleModule } from '@angular/material/slide-toggle';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { PlConfigBranchService } from '../../services/pl-config-branch-service.service';
+import { PlConfigTypesService } from '../../services/pl-config-types.service';
import { writeFeature } from '../../types/pl-config-features';
import { AddFeatureDialogComponent } from './add-feature-dialog.component';
@@ -11,11 +19,13 @@
beforeEach(async () => {
const branchService = jasmine.createSpyObj('PlConfigBranchService', ['getBranchApplicability',]);
+ const typesService = jasmine.createSpyObj('PlConfigTypesService', [], ['productApplicabilityTypes']);
await TestBed.configureTestingModule({
+ imports:[MatFormFieldModule,MatListModule,MatDialogModule,MatInputModule, MatSelectModule,FormsModule, NoopAnimationsModule, MatSlideToggleModule],
declarations: [AddFeatureDialogComponent],
- providers:[{
- provide: PlConfigBranchService, useValue: branchService
- },
+ providers: [
+ { provide: PlConfigBranchService, useValue: branchService },
+ { provide: PlConfigTypesService, useValue: typesService },
{ provide: MatDialogRef, useValue: {} },
{
provide: MAT_DIALOG_DATA, useValue: {
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/applicability-table/applicability-table.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/applicability-table/applicability-table.component.spec.ts
index 4378e17..72aaf06 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/applicability-table/applicability-table.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/applicability-table/applicability-table.component.spec.ts
@@ -1,4 +1,14 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatDialog, MatDialogModule } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatListModule } from '@angular/material/list';
+import { MatPaginatorModule } from '@angular/material/paginator';
+import { MatSelectModule } from '@angular/material/select';
+import { MatTableModule } from '@angular/material/table';
+import { MatTooltipModule } from '@angular/material/tooltip';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { of } from 'rxjs';
import { PlConfigBranchService } from '../../services/pl-config-branch-service.service';
import { PlConfigCurrentBranchService } from '../../services/pl-config-current-branch.service';
@@ -14,8 +24,10 @@
const branchServiceSpy = jasmine.createSpyObj('PlConfigBranchService',['modifyConfiguration'])
await TestBed.configureTestingModule({
+ imports:[MatFormFieldModule,MatListModule,MatDialogModule,MatInputModule,FormsModule, MatSelectModule, NoopAnimationsModule,MatTableModule, MatPaginatorModule,MatTooltipModule, MatPaginatorModule],
declarations: [ApplicabilityTableComponent],
providers: [
+ { provide: MatDialog, useValue: {} },
{ provide: PlConfigBranchService, useValue: branchServiceSpy },
{
provide: PlConfigCurrentBranchService, useValue: {
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/branch-selector/branch-selector.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/branch-selector/branch-selector.component.spec.ts
index 54472ac..d5cca0c 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/branch-selector/branch-selector.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/branch-selector/branch-selector.component.spec.ts
@@ -1,6 +1,12 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
+import { MatSelectModule } from '@angular/material/select';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { of } from 'rxjs';
import { PlConfigBranchService } from '../../services/pl-config-branch-service.service';
+import { PlConfigCurrentBranchService } from '../../services/pl-config-current-branch.service';
import { testBranchListing } from '../../testing/mockBranchService';
import { BranchSelectorComponent } from './branch-selector.component';
@@ -11,10 +17,15 @@
beforeEach(async () => {
const branchService = jasmine.createSpyObj('PlConfigBranchService', ['getBranches']);
+ const currentBranchService = jasmine.createSpyObj('PlConfigCurrentBranchService', [], ['viewBranchType','branchListing']);
const getBranchSpy = branchService.getBranches.and.returnValue(of(testBranchListing));
await TestBed.configureTestingModule({
+ imports:[MatFormFieldModule,NoopAnimationsModule,MatSelectModule,MatProgressSpinnerModule, FormsModule],
declarations: [BranchSelectorComponent],
- providers:[{provide: PlConfigBranchService,useValue:branchService}]
+ providers: [
+ { provide: PlConfigBranchService, useValue: branchService },
+ { provide: PlConfigCurrentBranchService, useValue: currentBranchService}
+ ]
})
.compileComponents();
});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/branch-type-selector/branch-type-selector.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/branch-type-selector/branch-type-selector.component.spec.ts
index 09a63b0..a2038d5 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/branch-type-selector/branch-type-selector.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/branch-type-selector/branch-type-selector.component.spec.ts
@@ -1,4 +1,7 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatRadioModule } from '@angular/material/radio';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { BranchTypeSelectorComponent } from './branch-type-selector.component';
@@ -8,6 +11,7 @@
beforeEach(async () => {
await TestBed.configureTestingModule({
+ imports:[NoopAnimationsModule,MatRadioModule, FormsModule],
declarations: [ BranchTypeSelectorComponent ]
})
.compileComponents();
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/commit-branch-dialog/commit-branch-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/commit-branch-dialog/commit-branch-dialog.component.spec.ts
index bf965c7..86d480a 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/commit-branch-dialog/commit-branch-dialog.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/commit-branch-dialog/commit-branch-dialog.component.spec.ts
@@ -1,5 +1,10 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { FormsModule } from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatSelectModule } from '@angular/material/select';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { of } from 'rxjs';
import { PlConfigActionService } from '../../services/pl-config-action.service';
@@ -49,6 +54,7 @@
},
]
await TestBed.configureTestingModule({
+ imports:[MatButtonModule,NoopAnimationsModule,MatSelectModule,MatFormFieldModule,FormsModule,MatDialogModule],
declarations: [CommitBranchDialogComponent],
providers: [
{ provide: MatDialogRef, useValue: {} },
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/config-group-dialog/config-group-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/config-group-dialog/config-group-dialog.component.spec.ts
index 4dddd27..b018357 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/config-group-dialog/config-group-dialog.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/config-group-dialog/config-group-dialog.component.spec.ts
@@ -1,4 +1,10 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatListModule } from '@angular/material/list';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { ConfigGroupDialogComponent } from './config-group-dialog.component';
@@ -8,7 +14,36 @@
beforeEach(async () => {
await TestBed.configureTestingModule({
- declarations: [ ConfigGroupDialogComponent ]
+ imports:[MatDialogModule,MatFormFieldModule,MatInputModule,MatListModule,NoopAnimationsModule,FormsModule],
+ declarations: [ConfigGroupDialogComponent],
+ providers: [
+ { provide: MatDialogRef, useValue: {} },
+ {
+ provide: MAT_DIALOG_DATA, useValue: {
+ editable: true,
+ configGroup: {
+ id: "1",
+ name: "Group 1",
+ views: [
+ {
+ id: "2",
+ name: "View 1",
+ hasFeatureApplicabilities:true,
+ },
+ {
+ id: "3",
+ name: "View 2",
+ hasFeatureApplicabilities:true,
+ },
+ {
+ id: "4",
+ name: "View 3",
+ hasFeatureApplicabilities:true,
+ }
+ ]
+ }
+ }}
+ ]
})
.compileComponents();
});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/configuration-dropdown/configuration-dropdown.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/configuration-dropdown/configuration-dropdown.component.spec.ts
index b3f6ea9..5fbd4df 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/configuration-dropdown/configuration-dropdown.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/configuration-dropdown/configuration-dropdown.component.spec.ts
@@ -1,4 +1,5 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MatButtonModule } from '@angular/material/button';
import { MatDialog } from '@angular/material/dialog';
import { MatMenuModule } from '@angular/material/menu';
import { of } from 'rxjs';
@@ -38,7 +39,7 @@
var copyConfigurationSpy = branchService.copyConfiguration.and.returnValue(of(testResponse));
var delteConfigurationSpy = branchService.deleteConfiguration.and.returnValue(of(testResponse));
await TestBed.configureTestingModule({
- imports:[MatMenuModule],
+ imports:[MatMenuModule,MatButtonModule],
declarations: [ConfigurationDropdownComponent],
providers: [
{ provide: MatDialog, useValue: {} },
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/configuration-group-dropdown/configuration-group-dropdown.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/configuration-group-dropdown/configuration-group-dropdown.component.spec.ts
index 6661f21..2d1a471 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/configuration-group-dropdown/configuration-group-dropdown.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/configuration-group-dropdown/configuration-group-dropdown.component.spec.ts
@@ -1,4 +1,11 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MatButtonModule } from '@angular/material/button';
+import { MatDialog } from '@angular/material/dialog';
+import { MatMenuModule } from '@angular/material/menu';
+import { of } from 'rxjs';
+import { PlConfigCurrentBranchService } from '../../services/pl-config-current-branch.service';
+import { PlConfigUIStateService } from '../../services/pl-config-uistate.service';
+import { testBranchApplicability, testCfgGroups } from '../../testing/mockBranchService';
import { ConfigurationGroupDropdownComponent } from './configuration-group-dropdown.component';
@@ -7,8 +14,21 @@
let fixture: ComponentFixture<ConfigurationGroupDropdownComponent>;
beforeEach(async () => {
+ const currentBranchService = jasmine.createSpyObj('PlConfigCurrentBranchService', [], ['cfgGroups', 'branchApplicability']);
+ const uiService = jasmine.createSpyObj('PlConfigUIStateService', [], ['updateReqConfig']);
await TestBed.configureTestingModule({
- declarations: [ ConfigurationGroupDropdownComponent ]
+ imports:[MatMenuModule,MatButtonModule],
+ declarations: [ConfigurationGroupDropdownComponent],
+ providers: [
+ { provide: MatDialog, useValue: {} },
+ {
+ provide: PlConfigCurrentBranchService, useValue: {
+ branchApplicability: of(testBranchApplicability),
+ cfgGroups: of(testCfgGroups)
+ }
+ },
+ { provide: PlConfigUIStateService, useValue: uiService}
+ ]
})
.compileComponents();
});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/copy-configuration-dialog/copy-configuration-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/copy-configuration-dialog/copy-configuration-dialog.component.spec.ts
index bc13f78..a0e2ac9 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/copy-configuration-dialog/copy-configuration-dialog.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/copy-configuration-dialog/copy-configuration-dialog.component.spec.ts
@@ -1,4 +1,10 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MatButtonModule } from '@angular/material/button';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatSelectModule } from '@angular/material/select';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { PlConfigBranchService } from '../../services/pl-config-branch-service.service';
import { CopyConfigurationDialogComponent } from './copy-configuration-dialog.component';
@@ -7,8 +13,24 @@
let fixture: ComponentFixture<CopyConfigurationDialogComponent>;
beforeEach(async () => {
+ const branchService = jasmine.createSpyObj('PlConfigBranchService', ['getBranchApplicability']);
await TestBed.configureTestingModule({
- declarations: [ CopyConfigurationDialogComponent ]
+ imports:[MatSelectModule,MatFormFieldModule,NoopAnimationsModule,MatDialogModule,MatButtonModule],
+ declarations: [CopyConfigurationDialogComponent],
+ providers: [
+ { provide: PlConfigBranchService, useValue: branchService },
+ { provide: MatDialogRef, useValue: {} },
+ {
+ provide: MAT_DIALOG_DATA, useValue: {
+ currentConfig:
+ {
+ id: '',
+ name: ''
+ },
+ currentBranch:'10'
+ }
+ }
+ ]
})
.compileComponents();
});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/create-action-dialog/create-action-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/create-action-dialog/create-action-dialog.component.spec.ts
index 5e6b6a0..abf15da 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/create-action-dialog/create-action-dialog.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/create-action-dialog/create-action-dialog.component.spec.ts
@@ -1,5 +1,11 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { FormsModule } from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatSelectModule } from '@angular/material/select';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { of } from 'rxjs';
import { PlConfigActionService } from '../../services/pl-config-action.service';
@@ -11,6 +17,7 @@
beforeEach(async () => {
await TestBed.configureTestingModule({
+ imports:[MatFormFieldModule,MatSelectModule,MatInputModule,MatButtonModule,MatDialogModule,NoopAnimationsModule, FormsModule],
declarations: [CreateActionDialogComponent],
providers: [
{ provide: MatDialogRef, useValue: {} },
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/edit-config-dialog/edit-config-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/edit-config-dialog/edit-config-dialog.component.spec.ts
index 36aea13..5a87975 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/edit-config-dialog/edit-config-dialog.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/edit-config-dialog/edit-config-dialog.component.spec.ts
@@ -1,20 +1,36 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { FormsModule } from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatListModule } from '@angular/material/list';
+import { MatSelectModule } from '@angular/material/select';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { of } from 'rxjs';
import { PlConfigBranchService } from '../../services/pl-config-branch-service.service';
+import { PlConfigCurrentBranchService } from '../../services/pl-config-current-branch.service';
+import { PlConfigTypesService } from '../../services/pl-config-types.service';
import { testBranchApplicability } from '../../testing/mockBranchService';
import { PlConfigApplicUIBranchMapping } from '../../types/pl-config-applicui-branch-mapping';
import { EditConfigurationDialogComponent } from './edit-config-dialog.component';
-describe('EditDialogComponent', () => {
+describe('EditConfigDialogComponent', () => {
let component: EditConfigurationDialogComponent;
let fixture: ComponentFixture<EditConfigurationDialogComponent>;
beforeEach(async () => {
+ const typesService = jasmine.createSpyObj('PlConfigTypesService', [], ['productApplicabilityTypes']);
+ const currentBranchService = jasmine.createSpyObj('PlConfigCurrentBranchService', [], ['cfgGroups']);
+ const branchService = jasmine.createSpyObj('PlConfigBranchService', ['getBranchApplicability']);
await TestBed.configureTestingModule({
+ imports:[MatFormFieldModule,MatInputModule,MatSelectModule,MatDialogModule,NoopAnimationsModule,MatListModule,MatButtonModule, FormsModule],
declarations: [EditConfigurationDialogComponent],
providers: [
+ { provide: PlConfigBranchService, useValue: branchService },
+ { provide: PlConfigCurrentBranchService, useValue: currentBranchService },
+ { provide: PlConfigTypesService, useValue: typesService },
{ provide: MatDialogRef, useValue: {} },
{
provide: MAT_DIALOG_DATA, useValue: {
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/edit-feature-dialog/edit-feature-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/edit-feature-dialog/edit-feature-dialog.component.spec.ts
index 568afbe..fa9ab45 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/edit-feature-dialog/edit-feature-dialog.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/edit-feature-dialog/edit-feature-dialog.component.spec.ts
@@ -1,7 +1,16 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { FormsModule } from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatListModule } from '@angular/material/list';
+import { MatSelectModule } from '@angular/material/select';
+import { MatSlideToggleModule } from '@angular/material/slide-toggle';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { of } from 'rxjs';
import { PlConfigBranchService } from '../../services/pl-config-branch-service.service';
+import { PlConfigTypesService } from '../../services/pl-config-types.service';
import { testBranchApplicability } from '../../testing/mockBranchService';
import { PlConfigApplicUIBranchMapping } from '../../types/pl-config-applicui-branch-mapping';
@@ -12,12 +21,17 @@
let fixture: ComponentFixture<EditFeatureDialogComponent>;
beforeEach(async () => {
+ const typesService = jasmine.createSpyObj('PlConfigTypesService', [], ['productApplicabilityTypes']);
await TestBed.configureTestingModule({
+ imports:[MatFormFieldModule,MatInputModule,MatButtonModule,MatListModule,MatSelectModule,MatDialogModule,NoopAnimationsModule, MatSlideToggleModule, FormsModule],
declarations: [EditFeatureDialogComponent],
- providers: [{ provide: MatDialogRef, useValue: {} },
+ providers: [
+ { provide: PlConfigTypesService, useValue: typesService },
+ { provide: MatDialogRef, useValue: {} },
{
provide: MAT_DIALOG_DATA, useValue: {
currentBranch: "01238082141",
+ editable:true,
feature: {
id: '',
idIntValue: 6451325,
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/feature-dropdown/feature-dropdown.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/feature-dropdown/feature-dropdown.component.spec.ts
index f470948..f1eec06 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/feature-dropdown/feature-dropdown.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/feature-dropdown/feature-dropdown.component.spec.ts
@@ -1,4 +1,5 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MatButtonModule } from '@angular/material/button';
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { MatMenuModule } from '@angular/material/menu';
import { of } from 'rxjs';
@@ -38,7 +39,7 @@
const deleteFeatureSpy = branchService.deleteFeature.and.returnValue(of(testResponse));
const modifyFeatureSpy = branchService.modifyFeature.and.returnValue(of(testResponse));
await TestBed.configureTestingModule({
- imports:[MatMenuModule],
+ imports:[MatMenuModule,MatButtonModule],
declarations: [FeatureDropdownComponent],
providers: [
{
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/transition-action-to-review-dialog/transition-action-to-review-dialog.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/transition-action-to-review-dialog/transition-action-to-review-dialog.component.spec.ts
index f3af308..ade3a2f 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/transition-action-to-review-dialog/transition-action-to-review-dialog.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/components/transition-action-to-review-dialog/transition-action-to-review-dialog.component.spec.ts
@@ -1,5 +1,10 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { FormsModule } from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatSelectModule } from '@angular/material/select';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { of } from 'rxjs';
import { PlConfigActionService } from '../../services/pl-config-action.service';
@@ -49,6 +54,7 @@
},
]
await TestBed.configureTestingModule({
+ imports:[MatDialogModule,MatSelectModule,MatButtonModule,MatFormFieldModule,FormsModule,NoopAnimationsModule],
declarations: [TransitionActionToReviewDialogComponent],
providers: [
{ provide: MatDialogRef, useValue: {} },
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/plconfig.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/plconfig.component.spec.ts
index c5995ac..3d28d86 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/plconfig.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/plconfig.component.spec.ts
@@ -1,6 +1,27 @@
+import { HttpClientModule } from '@angular/common/http';
import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { FormsModule } from '@angular/forms';
+import { MatButtonModule } from '@angular/material/button';
+import { MatDialogModule } from '@angular/material/dialog';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatMenuModule } from '@angular/material/menu';
+import { MatPaginatorModule } from '@angular/material/paginator';
+import { MatRadioModule } from '@angular/material/radio';
+import { MatSelectModule } from '@angular/material/select';
+import { MatTableModule } from '@angular/material/table';
+import { MatTooltipModule } from '@angular/material/tooltip';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { ActivatedRoute, convertToParamMap, Router } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
import { of } from 'rxjs';
+import { ActionDropDownComponent } from './components/action-drop-down/action-drop-down.component';
+import { ApplicabilityTableComponent } from './components/applicability-table/applicability-table.component';
+import { BranchSelectorComponent } from './components/branch-selector/branch-selector.component';
+import { BranchTypeSelectorComponent } from './components/branch-type-selector/branch-type-selector.component';
+import { ConfigurationDropdownComponent } from './components/configuration-dropdown/configuration-dropdown.component';
+import { ConfigurationGroupDropdownComponent } from './components/configuration-group-dropdown/configuration-group-dropdown.component';
+import { FeatureDropdownComponent } from './components/feature-dropdown/feature-dropdown.component';
import { PlconfigComponent } from './plconfig.component';
@@ -10,7 +31,32 @@
beforeEach(async () => {
await TestBed.configureTestingModule({
- declarations: [PlconfigComponent],
+ imports: [
+ HttpClientModule,
+ MatDialogModule,
+ MatMenuModule,
+ RouterTestingModule,
+ MatTableModule,
+ MatFormFieldModule,
+ FormsModule,
+ MatInputModule,
+ MatSelectModule,
+ MatRadioModule,
+ MatTooltipModule,
+ MatPaginatorModule,
+ MatButtonModule,
+ NoopAnimationsModule
+ ],
+ declarations: [
+ PlconfigComponent,
+ ApplicabilityTableComponent,
+ BranchSelectorComponent,
+ BranchTypeSelectorComponent,
+ ConfigurationDropdownComponent,
+ ActionDropDownComponent,
+ ConfigurationGroupDropdownComponent,
+ FeatureDropdownComponent,
+ ],
providers: [{ provide: Router, useValue: { navigate: () => { }}},
{
provide: ActivatedRoute, useValue: {
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/plconfig.module.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/plconfig.module.ts
index 6788579..6216377 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/plconfig.module.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/plconfig.module.ts
@@ -14,7 +14,7 @@
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatInputModule } from '@angular/material/input';
import { MatMenuModule } from '@angular/material/menu';
-import { MatButtonModule } from '@angular/material/button';
+//import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule } from '@angular/material/dialog';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { MatTooltipModule } from '@angular/material/tooltip';
@@ -43,6 +43,8 @@
import { AddConfigurationGroupDialogComponent } from './components/add-configuration-group-dialog/add-configuration-group-dialog.component';
import { ConfigGroupDialogComponent } from './components/config-group-dialog/config-group-dialog.component';
+import { PleSharedMaterialModule } from '../ple-shared-material/ple-shared-material.module'
+
@NgModule({
@@ -57,7 +59,8 @@
MatPaginatorModule,
MatInputModule,
MatMenuModule,
- MatButtonModule,
+ //MatButtonModule,
+ PleSharedMaterialModule,
MatDialogModule,
MatSlideToggleModule,
MatTooltipModule,
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/services/pl-config-types.service.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/services/pl-config-types.service.spec.ts
index 23c6b31..a96694c 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/services/pl-config-types.service.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/services/pl-config-types.service.spec.ts
@@ -1,12 +1,19 @@
+import { HttpClient } from '@angular/common/http';
import { TestBed } from '@angular/core/testing';
import { PlConfigTypesService } from './pl-config-types.service';
describe('PlConfigTypesService', () => {
let service: PlConfigTypesService;
+ let httpClientSpy: jasmine.SpyObj<HttpClient>;
beforeEach(() => {
- TestBed.configureTestingModule({});
+ httpClientSpy = jasmine.createSpyObj('HttpClient', ['get', 'put', 'post']);
+ TestBed.configureTestingModule({
+ providers: [
+ {provide: HttpClient, useValue:httpClientSpy}
+ ]
+ });
service = TestBed.inject(PlConfigTypesService);
});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/testing/mockBranchService.ts b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/testing/mockBranchService.ts
index a0225fd..c33cecd 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/plconfig/testing/mockBranchService.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/plconfig/testing/mockBranchService.ts
@@ -1,6 +1,33 @@
import { PlConfigApplicUIBranchMapping } from "../types/pl-config-applicui-branch-mapping"
import { PlConfigBranchListingBranch } from "../types/pl-config-branch"
+
+export const testCfgGroups = [
+ {
+ id: '1',
+ name:'Group 1'
+ },
+ {
+ id: '2',
+ name:'Group 2'
+ },
+ {
+ id: '3',
+ name:'Group 3'
+ },
+ {
+ id: '4',
+ name:'Group 4'
+ },
+ {
+ id: '5',
+ name:'Group 5'
+ },
+ {
+ id: '6',
+ name:'Group 6'
+ }
+]
export const testBranchInfo =
{
id: "3182843164128526558",
@@ -32,99 +59,7 @@
viewId : "-1",
idIntValue : -1918287650
},
- editable: true,
- featureIdToFeature:
- {
- 758071644:
- {
- id: "758071644",
- name : "JHU_CONTROLLER",
- values:
- [
- "Included",
- "Excluded"
- ],
- defaultValue: "Included",
- description : "A small point of variation",
- multiValued : false,
- valueType : "String",
- type : null,
- productApplicabilities:
- [
-
- ],
- idIntValue : 758071644,
- idString : "758071644"
- },
- 130553732:
- {
- id : "130553732",
- name : "ROBOT_ARM_LIGHT",
- values:
- [
- "Included",
- "Excluded"
- ],
- defaultValue: "Included",
- description : "A significant capability",
- multiValued : false,
- valueType : "String",
- type : null,
- productApplicabilities:
- [
- "OFP"
- ],
- idIntValue : 130553732,
- idString : "130553732"
- },
- 1939294030:
- {
- id : "1939294030",
- name : "ENGINE_5",
- values : [ "A2543", "B5543" ],
- defaultValue : "A2543",
- description : "Used select type of engine",
- multiValued : false,
- valueType : "String",
- type : null,
- productApplicabilities:
- [
- "OFP"
- ],
- idIntValue : 1939294030,
- idString : "1939294030"
- },
- 293076452:
- {
- id : "293076452",
- name : "ROBOT_SPEAKER",
- values:
- [
- "SPKR_A",
- "SPKR_B",
- "SPKR_C"
- ],
- defaultValue : "SPKR_A",
- description : "This feature is multi-select.",
- multiValued : true,
- valueType : "String",
- type : null,
- productApplicabilities:
- [
-
- ],
- idIntValue : 293076452,
- idString : "293076452"
- }
- },
- featureToValueMaps:
- [
- {
- description: "This is a feature",
- feature: "feature1",
- id:"12345"
- }
- ],
+ editable: true,
features:
[
{
@@ -146,6 +81,12 @@
],
idIntValue: 1939294030,
idString: "1939294030",
+ configurations: [
+ {
+ id: "12345",
+ name:"group1"
+ }
+ ],
setValueStr(): void {
},
@@ -172,6 +113,12 @@
],
idIntValue : 758071644,
idString: "758071644",
+ configurations: [
+ {
+ id: "12345",
+ name:"group1"
+ }
+ ],
setValueStr(): void {
},
@@ -197,7 +144,13 @@
"OFP"
],
idIntValue : 130553732,
- idString : "130553732",
+ idString: "130553732",
+ configurations: [
+ {
+ id: "12345",
+ name:"group1"
+ }
+ ],
setValueStr(): void {
},
@@ -225,6 +178,12 @@
],
idIntValue : 293076452,
idString: "293076452",
+ configurations: [
+ {
+ id: "12345",
+ name:"group1"
+ }
+ ],
setValueStr(): void {
},
@@ -233,19 +192,18 @@
}
}
],
- featuresOrdered:
- [
- "ENGINE_5",
- "JHU_CONTROLLER",
- "ROBOT_ARM_LIGHT",
- "ROBOT_SPEAKER"
- ],
groups:
[
{
id : "736857919",
- name : "abGroup"
- }
+ name: "abGroup",
+ hasFeatureApplicabilities:true,
+ configurations: [
+ "293076452",
+ "130553732"
+ ],
+ productApplicabilities:[]
+ },
],
parentBranch:
{
@@ -258,28 +216,25 @@
[
{
id: "200045",
- name : "Product A"
+ name: "Product A",
+ hasFeatureApplicabilities: true,
},
{
id : "200046",
- name : "Product B"
+ name: "Product B",
+ hasFeatureApplicabilities: true,
},
{
id : "200047",
- name : "Product C"
+ name: "Product C",
+ hasFeatureApplicabilities: true,
},
{
id : "200048",
- name : "Product D"
+ name: "Product D",
+ hasFeatureApplicabilities: true,
}
- ],
- viewsOrdered:
- [
- "Product A",
- "Product B",
- "Product C",
- "Product D"
- ],
+ ],
}
export const testBranchListing: PlConfigBranchListingBranch[] = [
{
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/ple-routing.module.ts b/plugins/org.eclipse.osee.web/src/app/ple/ple-routing.module.ts
index 9330363..a38594c 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/ple-routing.module.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/ple-routing.module.ts
@@ -3,15 +3,15 @@
import { PleComponent } from './ple.component';
const routes: Routes = [
- //{ path: '', component: PleComponent }
{
path: 'plconfig',
loadChildren: () => import('./plconfig/plconfig.module').then(m => m.PlconfigModule),
},
{
- path: 'ple', //todo remove when ple app page is made
- redirectTo: 'plconfig',
+ path: '',
+ component: PleComponent,
},
+ { path: 'messaging', loadChildren: () => import('./messaging/messaging.module').then(m => m.MessagingModule) },
{
path: '**',//todo remove when pl app page is made
redirectTo:'plconfig',
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/ple-shared-material/ple-shared-material.module.ts b/plugins/org.eclipse.osee.web/src/app/ple/ple-shared-material/ple-shared-material.module.ts
new file mode 100644
index 0000000..ebe90e2
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/app/ple/ple-shared-material/ple-shared-material.module.ts
@@ -0,0 +1,16 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { MatButtonModule } from '@angular/material/button';
+
+
+
+@NgModule({
+ declarations: [],
+ imports: [
+ CommonModule,
+ ],
+ exports: [
+ MatButtonModule,
+ ]
+})
+export class PleSharedMaterialModule { }
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/ple.component.html b/plugins/org.eclipse.osee.web/src/app/ple/ple.component.html
index c9e8a1e..1eb2e4a 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/ple.component.html
+++ b/plugins/org.eclipse.osee.web/src/app/ple/ple.component.html
@@ -1 +1,13 @@
-<p>ple works!</p>
+<div style="height:100%">
+ <div class ="ple-app-container">
+ <div class="ple-buttons-section">
+ <div class ="mat-display-4">
+ Product Line Engineering
+ </div>
+ <div class="ple-button-selection-section">
+ <button mat-raised-button color="primary" (click)="navigateTo('plconfig')">Go to Product Line Configuration</button>
+ <button mat-raised-button color="primary">Go to Message Configuration</button>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/ple.component.sass b/plugins/org.eclipse.osee.web/src/app/ple/ple.component.sass
index e69de29..b3c5d5c 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/ple.component.sass
+++ b/plugins/org.eclipse.osee.web/src/app/ple/ple.component.sass
@@ -0,0 +1,26 @@
+body
+ height: 100%
+ width: 100%
+:host
+ display: inline-block
+ height: 100%
+ width: 100%
+.ple-buttons-section
+ width: 100%
+ height: 100%
+ padding-top: 10%
+ display: flex
+ align-items: center
+ justify-content: space-evenly
+ flex-direction: column
+.ple-button-selection-section
+ width: 60%
+ height: 20%
+ display: flex
+ justify-content: space-around
+.ple-app-container
+ display: flex
+ height: 100%
+ align-items: flex-end
+.mat-raised-button
+ height: 100%
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/ple.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/ple/ple.component.spec.ts
index eec3fb2..592abd9 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/ple.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/ple.component.spec.ts
@@ -1,14 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MatButtonModule } from '@angular/material/button';
+import { Router, ActivatedRoute } from '@angular/router';
+import { RouterTestingModule } from '@angular/router/testing';
import { PleComponent } from './ple.component';
describe('PleComponent', () => {
let component: PleComponent;
let fixture: ComponentFixture<PleComponent>;
+ let router:any;
beforeEach(async () => {
+ router = jasmine.createSpyObj('Router', ['navigate']);
await TestBed.configureTestingModule({
- declarations: [ PleComponent ]
+ imports:[MatButtonModule, RouterTestingModule],
+ declarations: [PleComponent],
+ providers: [{ provide: Router, useValue: router},
+ { provide: ActivatedRoute, useValue: {} },
+ ]
})
.compileComponents();
});
@@ -22,4 +31,10 @@
it('should create', () => {
expect(component).toBeTruthy();
});
+
+ it('should navigate to plconfig', () => {
+ component.navigateTo('plconfig');
+ expect(router.navigate).toHaveBeenCalledWith(['plconfig'],{relativeTo: undefined, queryParamsHandling:'merge'});
+ //expect(component).toBeTruthy();
+ });
});
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/ple.component.ts b/plugins/org.eclipse.osee.web/src/app/ple/ple.component.ts
index 5d0c28c..b06bf93 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/ple.component.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/ple.component.ts
@@ -1,15 +1,21 @@
import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
@Component({
- selector: 'app-ple',
+ selector: 'ple-main',
templateUrl: './ple.component.html',
styleUrls: ['./ple.component.sass']
})
export class PleComponent implements OnInit {
- constructor() { }
+ constructor(private route: ActivatedRoute, private router: Router) { }
ngOnInit(): void {
}
-
+ navigateTo(location: string) {
+ this.router.navigate([location], {
+ relativeTo: this.route.parent,
+ queryParamsHandling: 'merge',
+ });
+ }
}
diff --git a/plugins/org.eclipse.osee.web/src/app/ple/ple.module.ts b/plugins/org.eclipse.osee.web/src/app/ple/ple.module.ts
index 36b0068..9df517e 100644
--- a/plugins/org.eclipse.osee.web/src/app/ple/ple.module.ts
+++ b/plugins/org.eclipse.osee.web/src/app/ple/ple.module.ts
@@ -3,13 +3,15 @@
import { PleRoutingModule } from './ple-routing.module';
import { PleComponent } from './ple.component';
+import { PleSharedMaterialModule } from './ple-shared-material/ple-shared-material.module';
@NgModule({
declarations: [PleComponent],
imports: [
CommonModule,
- PleRoutingModule
+ PleRoutingModule,
+ PleSharedMaterialModule
]
})
export class PleModule { }
diff --git a/plugins/org.eclipse.osee.web/src/app/userdata/components/display-user/display-user.component.spec.ts b/plugins/org.eclipse.osee.web/src/app/userdata/components/display-user/display-user.component.spec.ts
index cb263bf..5a4f0ca 100644
--- a/plugins/org.eclipse.osee.web/src/app/userdata/components/display-user/display-user.component.spec.ts
+++ b/plugins/org.eclipse.osee.web/src/app/userdata/components/display-user/display-user.component.spec.ts
@@ -1,3 +1,4 @@
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DisplayUserComponent } from './display-user.component';
@@ -5,12 +6,15 @@
describe('DisplayUserComponent', () => {
let component: DisplayUserComponent;
let fixture: ComponentFixture<DisplayUserComponent>;
+ let httpTestingController: HttpTestingController;
beforeEach(async () => {
await TestBed.configureTestingModule({
+ imports:[HttpClientTestingModule],
declarations: [ DisplayUserComponent ]
})
- .compileComponents();
+ .compileComponents();
+ httpTestingController = TestBed.inject(HttpTestingController);
});
beforeEach(() => {
diff --git a/plugins/org.eclipse.osee.web/src/custom-theme.scss b/plugins/org.eclipse.osee.web/src/custom-theme.scss
index 6babf54..a88b394 100644
--- a/plugins/org.eclipse.osee.web/src/custom-theme.scss
+++ b/plugins/org.eclipse.osee.web/src/custom-theme.scss
@@ -2,7 +2,9 @@
// Custom Theming for Angular Material
// For more information: https://material.angular.io/guide/theming
-@use 'themes/plconfig/lib' as plconfig;
+// @use 'themes/ple/plconfig/lib' as plconfig;
+// @use 'themes/ple/messages/lib' as plmessages;
+@use 'themes/ple/lib' as ple;
@import 'modern-ple-theme.scss';
// Plus imports for other components in your app.
@@ -17,21 +19,24 @@
// that you are using.
@include angular-material-theme($modern-ple-light-theme);
- @include plconfig.table-theme($modern-ple-light-theme,$modern-ple-typography);
- @include plconfig.main-theme($modern-ple-light-theme);
- @include plconfig.dropdown-configuration-theme($modern-ple-light-theme);
- @include plconfig.dropdown-feature-theme($modern-ple-light-theme);
- @include plconfig.dropdown-configuration-group-theme($modern-ple-light-theme);
- @include plconfig.branch-selector-radio-theme($modern-ple-light-theme);
+ @include ple.plconfig-table-theme($modern-ple-light-theme,$modern-ple-typography);
+ @include ple.plconfig-main-theme($modern-ple-light-theme);
+ @include ple.plconfig-dropdown-configuration-theme($modern-ple-light-theme);
+ @include ple.plconfig-dropdown-feature-theme($modern-ple-light-theme);
+ @include ple.plconfig-dropdown-configuration-group-theme($modern-ple-light-theme);
+ @include ple.plconfig-branch-selector-radio-theme($modern-ple-light-theme);
+ @include ple.messages-messaging-message-interface-elements-theme($modern-ple-light-theme,$modern-ple-typography);
+ @include ple.messages-messaging-message-interface-interface-theme($modern-ple-light-theme,$modern-ple-typography);
+ @include ple.messages-messaging-message-interface-types-theme($modern-ple-light-theme,$modern-ple-typography);
.dark-theme{
@include angular-material-color($modern-ple-dark-theme);
- @include plconfig.table-color($modern-ple-dark-theme);
- @include plconfig.main-color($modern-ple-dark-theme);
- @include plconfig.dropdown-configuration-color($modern-ple-dark-theme);
- @include plconfig.dropdown-feature-color($modern-ple-dark-theme);
- @include plconfig.dropdown-configuration-group-color($modern-ple-dark-theme);
- @include plconfig.branch-selector-radio-color($modern-ple-dark-theme);
+ @include ple.plconfig-table-color($modern-ple-dark-theme);
+ @include ple.plconfig-main-color($modern-ple-dark-theme);
+ @include ple.plconfig-dropdown-configuration-color($modern-ple-dark-theme);
+ @include ple.plconfig-dropdown-feature-color($modern-ple-dark-theme);
+ @include ple.plconfig-dropdown-configuration-group-color($modern-ple-dark-theme);
+ @include ple.plconfig-branch-selector-radio-color($modern-ple-dark-theme);
}
diff --git a/plugins/org.eclipse.osee.web/src/environments/proxy.conf.json b/plugins/org.eclipse.osee.web/src/environments/proxy.conf.json
index d055f22..3333a64 100644
--- a/plugins/org.eclipse.osee.web/src/environments/proxy.conf.json
+++ b/plugins/org.eclipse.osee.web/src/environments/proxy.conf.json
@@ -16,5 +16,14 @@
"pathReWrite":{
"^/ats":""
}
+ },
+ "/mim/*":{
+ "target":"http://localhost:8089",
+ "secure":true,
+ "changeOrigin":true,
+ "logLevel":"debug",
+ "pathReWrite":{
+ "^/mim":""
+ }
}
}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/themes/ple/_lib.scss b/plugins/org.eclipse.osee.web/src/themes/ple/_lib.scss
new file mode 100644
index 0000000..103ec50
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/themes/ple/_lib.scss
@@ -0,0 +1,2 @@
+@forward 'messages/lib' as messages-*;
+@forward 'plconfig/lib' as plconfig-*;
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/themes/ple/messages/_lib.scss b/plugins/org.eclipse.osee.web/src/themes/ple/messages/_lib.scss
new file mode 100644
index 0000000..5466088
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/themes/ple/messages/_lib.scss
@@ -0,0 +1 @@
+@forward 'messaging/lib' as messaging-*;
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/_lib.scss b/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/_lib.scss
new file mode 100644
index 0000000..b1467fc
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/_lib.scss
@@ -0,0 +1 @@
+@forward 'message-interface/lib' as message-interface-*;
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/message-interface/_lib.scss b/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/message-interface/_lib.scss
new file mode 100644
index 0000000..44ba724
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/message-interface/_lib.scss
@@ -0,0 +1,3 @@
+@forward 'elements/lib' as elements-*;
+@forward 'interface/lib' as interface-*;
+@forward 'types/lib' as types-*;
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/message-interface/elements/_lib.scss b/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/message-interface/elements/_lib.scss
new file mode 100644
index 0000000..6af3335
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/message-interface/elements/_lib.scss
@@ -0,0 +1 @@
+@forward 'messaging-element-interface.theme.scss'
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/message-interface/elements/_messaging-element-interface.theme.scss b/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/message-interface/elements/_messaging-element-interface.theme.scss
new file mode 100644
index 0000000..b78e1af
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/message-interface/elements/_messaging-element-interface.theme.scss
@@ -0,0 +1,77 @@
+@import '~@angular/material/theming';
+
+@mixin color($config-or-theme) {
+ // Extract the color configuration in case a theme has been passed.
+ // This allows consumers to either pass a theme object or a color configuration.
+ $config: mat-get-color-config($config-or-theme);
+ // Extract the palettes you need from the theme definition.
+ $primary: map-get($config, primary);
+ $accent: map-get($config, accent);
+ $warn: map-get($config, warn);
+ $background: map-get($config, background);
+ $foreground: map-get($config, foreground);
+
+ // Define any styles affected by the theme.
+ .message-element-interface-table-view-sub-message-header{
+ color: mat-color($primary)
+ }
+
+ .message-element-interface-table-view-message-header{
+ color:mat-color($primary,600)
+ }
+
+ .message-table-row-even{
+ background-color:mat-color($background, background)
+ }
+
+ .message-table-row-odd{
+ background-color:mat-color($background, selected-button)
+ }
+
+ tr.message-detail-row:not(.message-expanded-detail-row):hover {
+ background: mat-color($background,app-bar)
+ }
+
+ tr.message-detail-row:not(.message-expanded-detail-row):active {
+ background: mat-color($background,unselected-chip)
+ }
+
+ .message-table-sub-element-row-even{
+ background-color:mat-color($primary,50)
+ }
+
+ .message-table-sub-element-row-odd{
+ background-color:mat-color($primary,100)
+ }
+
+ .message-element-interface-table-view-element{
+ border-bottom: 0.5em solid mat-color($background,disabled-button-toggle)
+ }
+ .message-element-interface-table-sub-message-element-computed{
+ color: mat-color($foreground,secondary-text) //need to user test this
+ //color:mat-color($warn,900)
+ }
+
+ .ple-message-element-interface-table-highlighted-text{
+ color:mat-color($accent,900)
+ }
+}
+@mixin typography($config-or-theme){
+
+}
+@mixin typography-themed($config-or-theme){
+ $config: mat-get-typography-config($config-or-theme);
+}
+
+@mixin theme($theme, $typography){
+ $color: mat-get-color-config($theme);
+ $typography: mat-get-typography-config($typography);
+ @include typography($theme);
+
+ @if $color != null {
+ @include color($color);
+ }
+ @if $typography != null {
+ @include typography-themed($typography);
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/message-interface/interface/_lib.scss b/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/message-interface/interface/_lib.scss
new file mode 100644
index 0000000..355928f
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/message-interface/interface/_lib.scss
@@ -0,0 +1 @@
+@forward 'messaging-interface.theme.scss'
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/message-interface/interface/_messaging-interface.theme.scss b/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/message-interface/interface/_messaging-interface.theme.scss
new file mode 100644
index 0000000..293b539
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/message-interface/interface/_messaging-interface.theme.scss
@@ -0,0 +1,77 @@
+@import '~@angular/material/theming';
+
+@mixin color($config-or-theme) {
+ // Extract the color configuration in case a theme has been passed.
+ // This allows consumers to either pass a theme object or a color configuration.
+ $config: mat-get-color-config($config-or-theme);
+ // Extract the palettes you need from the theme definition.
+ $primary: map-get($config, primary);
+ $accent: map-get($config, accent);
+ $warn: map-get($config, warn);
+ $background: map-get($config, background);
+ $foreground: map-get($config, foreground);
+
+ // Define any styles affected by the theme.
+ .message-interface-table-view-sub-message-header{
+ color: mat-color($primary)
+ }
+
+ .message-interface-table-view-message-header{
+ color:mat-color($primary,600)
+ }
+
+ .message-table-row-even{
+ background-color:mat-color($background, background)
+ }
+
+ .message-table-row-odd{
+ background-color:mat-color($background, selected-button)
+ }
+
+ tr.message-detail-row:not(.message-expanded-detail-row):hover {
+ background: mat-color($background,app-bar)
+ }
+
+ tr.message-detail-row:not(.message-expanded-detail-row):active {
+ background: mat-color($background,unselected-chip)
+ }
+
+ .message-table-sub-message-row-even{
+ background-color:mat-color($primary,50)
+ }
+
+ .message-table-sub-message-row-odd{
+ background-color:mat-color($primary,100)
+ }
+
+ .message-interface-table-view-element{
+ border-bottom: 0.5em solid mat-color($background,disabled-button-toggle)
+ }
+ .message-interface-table-sub-message-computed{
+ color: mat-color($foreground,secondary-text) //need to user test this
+ //color:mat-color($warn,900)
+ }
+
+ .ple-message-interface-table-highlighted-text{
+ color:mat-color($accent,900)
+ }
+}
+@mixin typography($config-or-theme){
+
+}
+@mixin typography-themed($config-or-theme){
+ $config: mat-get-typography-config($config-or-theme);
+}
+
+@mixin theme($theme, $typography){
+ $color: mat-get-color-config($theme);
+ $typography: mat-get-typography-config($typography);
+ @include typography($theme);
+
+ @if $color != null {
+ @include color($color);
+ }
+ @if $typography != null {
+ @include typography-themed($typography);
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/message-interface/types/_lib.scss b/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/message-interface/types/_lib.scss
new file mode 100644
index 0000000..ed933b4
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/message-interface/types/_lib.scss
@@ -0,0 +1 @@
+@forward 'types-interface.theme.scss'
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/message-interface/types/types-interface.theme.scss b/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/message-interface/types/types-interface.theme.scss
new file mode 100644
index 0000000..851e7c7
--- /dev/null
+++ b/plugins/org.eclipse.osee.web/src/themes/ple/messages/messaging/message-interface/types/types-interface.theme.scss
@@ -0,0 +1,37 @@
+@import '~@angular/material/theming';
+
+@mixin color($config-or-theme) {
+ // Extract the color configuration in case a theme has been passed.
+ // This allows consumers to either pass a theme object or a color configuration.
+ $config: mat-get-color-config($config-or-theme);
+ // Extract the palettes you need from the theme definition.
+ $primary: map-get($config, primary);
+ $accent: map-get($config, accent);
+ $warn: map-get($config, warn);
+ $background: map-get($config, background);
+ $foreground: map-get($config, foreground);
+
+ // Define any styles affected by the theme.
+ .ple-messaging-type-grid-list{
+ background-color:mat-color($background, app-bar)
+ }
+}
+@mixin typography($config-or-theme){
+
+}
+@mixin typography-themed($config-or-theme){
+ $config: mat-get-typography-config($config-or-theme);
+}
+
+@mixin theme($theme, $typography){
+ $color: mat-get-color-config($theme);
+ $typography: mat-get-typography-config($typography);
+ @include typography($theme);
+
+ @if $color != null {
+ @include color($color);
+ }
+ @if $typography != null {
+ @include typography-themed($typography);
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.osee.web/src/themes/plconfig/_lib.scss b/plugins/org.eclipse.osee.web/src/themes/ple/plconfig/_lib.scss
similarity index 100%
rename from plugins/org.eclipse.osee.web/src/themes/plconfig/_lib.scss
rename to plugins/org.eclipse.osee.web/src/themes/ple/plconfig/_lib.scss
diff --git a/plugins/org.eclipse.osee.web/src/themes/plconfig/branch-selector/_branch-selector.theme.component.scss b/plugins/org.eclipse.osee.web/src/themes/ple/plconfig/branch-selector/_branch-selector.theme.component.scss
similarity index 100%
rename from plugins/org.eclipse.osee.web/src/themes/plconfig/branch-selector/_branch-selector.theme.component.scss
rename to plugins/org.eclipse.osee.web/src/themes/ple/plconfig/branch-selector/_branch-selector.theme.component.scss
diff --git a/plugins/org.eclipse.osee.web/src/themes/plconfig/branch-selector/_lib.scss b/plugins/org.eclipse.osee.web/src/themes/ple/plconfig/branch-selector/_lib.scss
similarity index 100%
rename from plugins/org.eclipse.osee.web/src/themes/plconfig/branch-selector/_lib.scss
rename to plugins/org.eclipse.osee.web/src/themes/ple/plconfig/branch-selector/_lib.scss
diff --git a/plugins/org.eclipse.osee.web/src/themes/plconfig/dropdown/_configuration-dropdown.theme.component.scss b/plugins/org.eclipse.osee.web/src/themes/ple/plconfig/dropdown/_configuration-dropdown.theme.component.scss
similarity index 100%
rename from plugins/org.eclipse.osee.web/src/themes/plconfig/dropdown/_configuration-dropdown.theme.component.scss
rename to plugins/org.eclipse.osee.web/src/themes/ple/plconfig/dropdown/_configuration-dropdown.theme.component.scss
diff --git a/plugins/org.eclipse.osee.web/src/themes/plconfig/dropdown/_configuration-group-dropdown.theme.component.scss b/plugins/org.eclipse.osee.web/src/themes/ple/plconfig/dropdown/_configuration-group-dropdown.theme.component.scss
similarity index 100%
rename from plugins/org.eclipse.osee.web/src/themes/plconfig/dropdown/_configuration-group-dropdown.theme.component.scss
rename to plugins/org.eclipse.osee.web/src/themes/ple/plconfig/dropdown/_configuration-group-dropdown.theme.component.scss
diff --git a/plugins/org.eclipse.osee.web/src/themes/plconfig/dropdown/_feature-dropdown.theme.component.scss b/plugins/org.eclipse.osee.web/src/themes/ple/plconfig/dropdown/_feature-dropdown.theme.component.scss
similarity index 100%
rename from plugins/org.eclipse.osee.web/src/themes/plconfig/dropdown/_feature-dropdown.theme.component.scss
rename to plugins/org.eclipse.osee.web/src/themes/ple/plconfig/dropdown/_feature-dropdown.theme.component.scss
diff --git a/plugins/org.eclipse.osee.web/src/themes/plconfig/dropdown/_lib.scss b/plugins/org.eclipse.osee.web/src/themes/ple/plconfig/dropdown/_lib.scss
similarity index 100%
rename from plugins/org.eclipse.osee.web/src/themes/plconfig/dropdown/_lib.scss
rename to plugins/org.eclipse.osee.web/src/themes/ple/plconfig/dropdown/_lib.scss
diff --git a/plugins/org.eclipse.osee.web/src/themes/plconfig/main/_lib.scss b/plugins/org.eclipse.osee.web/src/themes/ple/plconfig/main/_lib.scss
similarity index 100%
rename from plugins/org.eclipse.osee.web/src/themes/plconfig/main/_lib.scss
rename to plugins/org.eclipse.osee.web/src/themes/ple/plconfig/main/_lib.scss
diff --git a/plugins/org.eclipse.osee.web/src/themes/plconfig/main/_pl-config.theme.scss b/plugins/org.eclipse.osee.web/src/themes/ple/plconfig/main/_pl-config.theme.scss
similarity index 100%
rename from plugins/org.eclipse.osee.web/src/themes/plconfig/main/_pl-config.theme.scss
rename to plugins/org.eclipse.osee.web/src/themes/ple/plconfig/main/_pl-config.theme.scss
diff --git a/plugins/org.eclipse.osee.web/src/themes/plconfig/table/_applicability-table.theme.component.scss b/plugins/org.eclipse.osee.web/src/themes/ple/plconfig/table/_applicability-table.theme.component.scss
similarity index 100%
rename from plugins/org.eclipse.osee.web/src/themes/plconfig/table/_applicability-table.theme.component.scss
rename to plugins/org.eclipse.osee.web/src/themes/ple/plconfig/table/_applicability-table.theme.component.scss
diff --git a/plugins/org.eclipse.osee.web/src/themes/plconfig/table/_lib.scss b/plugins/org.eclipse.osee.web/src/themes/ple/plconfig/table/_lib.scss
similarity index 100%
rename from plugins/org.eclipse.osee.web/src/themes/plconfig/table/_lib.scss
rename to plugins/org.eclipse.osee.web/src/themes/ple/plconfig/table/_lib.scss