Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions public/static/locales/en/collections.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@
"noExternalAppsNote": "NOTE: $t(noExternalApps).",
"pageTitle": "Collection - {{name}}",
"remove": "Remove",
"retagApps": "Re-tag Apps",
"retagAppsMessage": "{{name}} currently has apps associated with it. Renaming the $t(featureName) will cause all the currently tagged apps to be re-tagged with the new $t(featureName) name. Do you wish to continue?",
"retagAppsTitle": "Rename $t(featureName) and re-tag associated apps?",
"searchApps": "Search to add apps",
"selectCollectionTitle": "Select a Collection",
"unfollow": "Unfollow",
Expand Down
14 changes: 10 additions & 4 deletions src/components/apps/listing/Listing.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,25 +239,31 @@ function Listing(props) {
},
});

// Fall back to the legacy `fullCollectionName` key so bookmarks and
// history minted before the collection-ID cutover still resolve; the
// backend accepts either identifier. Drop the fallback after cutover.
const collectionId = category?.collectionId ?? category?.fullCollectionName;

const { isFetching: appsInCollectionStatus, error: appsInCollectionError } =
useQuery({
queryKey: [
COLLECTION_APPS_QUERY,
{
name: category?.fullCollectionName,
collectionId,
sortField: orderBy,
sortDir: order,
appFilter: filter,
},
],
queryFn: () =>
getCollectionApps({
name: category?.fullCollectionName,
collectionId,
sortField: orderBy,
sortDir: order,
appFilter: filter,
}),
enabled: category?.id === constants.MY_COLLECTIONS,
enabled:
category?.id === constants.MY_COLLECTIONS && !!collectionId,
onSuccess: (resp) => {
trackIntercomEvent(IntercomEvents.VIEWED_APPS, {
systemId: selectedSystemId,
Expand Down Expand Up @@ -523,7 +529,7 @@ function Listing(props) {
let newCategory = {
id: constants.MY_COLLECTIONS,
name: collection.name,
fullCollectionName: collection.display_name,
collectionId: collection.id,
};
setSelected([]);
onRouteToListing &&
Expand Down
56 changes: 12 additions & 44 deletions src/components/collections/form/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";

import { announce } from "components/announcer/CyVerseAnnouncer";
import { INFO } from "components/announcer/AnnouncerConstants";
import { ERROR_CODES, getErrorCode } from "components/error/errorCode";
import TableLoading from "components/table/TableLoading";
import ConfirmationDialog from "components/utils/ConfirmationDialog";
import isQueryLoading from "components/utils/isQueryLoading";
import { useUserProfile } from "contexts/userProfile";
import {
Expand All @@ -32,10 +30,8 @@ import {

import FormFields from "./FormFields";
import { useTranslation } from "i18n";
import ids from "../ids";
import styles from "../styles";
import CollectionToolbar from "./Toolbar";
import constants from "constants.js";

const useStyles = makeStyles()(styles);

Expand All @@ -52,7 +48,6 @@ function CollectionsForm(props) {
const [apps, setApps] = useState([]);
const [queryError, setQueryError] = useState(null);
const [collectionNameSaved, setCollectionNameSaved] = useState(false);
const [showRetagAppsDlg, setShowRetagAppsDlg] = useState(false);

const queryClient = useQueryClient();

Expand All @@ -70,14 +65,14 @@ function CollectionsForm(props) {
COLLECTION_DETAILS_QUERY,
{
name: collectionName,
fullName: collection?.display_name,
collectionId: collection?.id,
userId: userProfile?.id,
},
],
queryFn: () =>
getCollectionDetails({
name: collectionName,
fullName: collection?.display_name,
collectionId: collection?.id,
userId: userProfile?.id,
}),
enabled: !isCreatingCollection,
Expand Down Expand Up @@ -176,28 +171,21 @@ function CollectionsForm(props) {
mutate: updateCollectionNameDescMutation,
status: updateCollectionNameDescStatus,
} = useMutation(updateCollectionNameDesc, {
onSuccess: (resp, { newAdmins, newApps, attr }) => {
onSuccess: (resp, { newAdmins, newApps }) => {
updateCollectionDetailsMutation({
name: resp?.name,
fullName: resp?.display_name,
collectionId: resp?.id,
oldAdmins: admins,
oldApps: apps,
newAdmins,
newApps,
attr,
});
},
onError: (error) => {
const errorCode = getErrorCode(error);

if (errorCode === ERROR_CODES.ERR_EXISTS) {
setShowRetagAppsDlg(true);
} else {
setQueryError({
message: t("updateCollectionNameDescError"),
object: error,
});
}
setQueryError({
message: t("updateCollectionNameDescError"),
object: error,
});
},
});

Expand All @@ -219,17 +207,16 @@ function CollectionsForm(props) {

const { mutate: createCollectionMutation, status: createCollectionStatus } =
useMutation(createCollection, {
onSuccess: (resp, { newAdmins, newApps, attr }) => {
onSuccess: (resp, { newAdmins, newApps }) => {
setCollection(resp);
setCollectionNameSaved(true);
updateCollectionDetailsMutation({
name: resp?.name,
fullName: resp?.display_name,
collectionId: resp?.id,
oldAdmins: admins,
oldApps: apps,
newAdmins,
newApps,
attr,
});
},
onError: (error) => {
Expand All @@ -256,7 +243,6 @@ function CollectionsForm(props) {
description: newDescription,
admins: newAdmins,
apps: newApps,
retagApps,
} = values;

const newName = untrimmedName.trim();
Expand All @@ -274,15 +260,13 @@ function CollectionsForm(props) {
mutation({
originalName: collectionName,
originalDescription: collection?.description,
fullName: collection?.display_name,
collectionId: collection?.id,
name: newName,
description: newDescription,
oldAdmins: admins,
oldApps: apps,
newAdmins,
newApps,
retagApps,
attr: constants.METADATA.COMMUNITY_ATTR,
});
};

Expand All @@ -301,19 +285,17 @@ function CollectionsForm(props) {
},
],
apps: apps,
retagApps: false,
}
: {
name: collectionName || "",
description: collection?.description || "",
admins: admins,
apps: apps,
retagApps: false,
}
}
onSubmit={handleSubmit}
>
{({ handleSubmit, setFieldValue, dirty }) => (
{({ handleSubmit, dirty }) => (
<>
<CollectionToolbar
parentId={parentId}
Expand Down Expand Up @@ -356,20 +338,6 @@ function CollectionsForm(props) {
/>
)}
</Paper>
<ConfirmationDialog
baseId={ids.RETAG_APPS_DLG}
open={showRetagAppsDlg}
onClose={() => setShowRetagAppsDlg(false)}
onConfirm={() => {
setShowRetagAppsDlg(false);
setFieldValue("retagApps", true);
handleSubmit();
}}
title={t("retagAppsTitle")}
contentText={t("retagAppsMessage", {
name: collectionName,
})}
/>
</>
)}
</Formik>
Expand Down
1 change: 0 additions & 1 deletion src/components/collections/ids.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ const ids = {
FOLLOW_COLLECTION_DLG: "followCollectionDlg",
HELP_DLG: "collectionHelpDlg",
NAME: "collectionName",
RETAG_APPS_DLG: "retagAppsDlg",
SUBJECT_SEARCH: "subjectSearch",
TABLE: "table",
TOOLBAR: "toolbar",
Expand Down
1 change: 0 additions & 1 deletion src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ const constants = {
TACC_LINK: "https://tacc.utexas.edu/",

METADATA: {
COMMUNITY_ATTR: "cyverse-community",
INSTANT_LAUNCH_LOCATION_ATTR: "ui_location",
INSTANT_LAUNCH_DASHBOARD: "dashboard",
INSTANT_LAUNCH_NAV_DRAWER: "nav_drawer",
Expand Down
66 changes: 22 additions & 44 deletions src/serviceFacades/groups.js
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ function getCollectionFollowers({ name }) {
});
}

function getCollectionApps({ name, sortField, sortDir, appFilter }) {
function getCollectionApps({ collectionId, sortField, sortDir, appFilter }) {
const params = {
"sort-field": sortField || "name",
"sort-dir": sortDir?.toUpperCase() || "ASC",
Expand All @@ -401,15 +401,17 @@ function getCollectionApps({ name, sortField, sortDir, appFilter }) {
}

return callApi({
endpoint: `/api/apps/communities/${encodeURIComponent(name)}/apps`,
endpoint: `/api/apps/communities/${encodeURIComponent(
collectionId
)}/apps`,
method: "GET",
params,
});
}

function getCollectionDetails({
name,
fullName,
collectionId,
userId,
sortField,
sortDir,
Expand All @@ -420,7 +422,7 @@ function getCollectionDetails({
getCollectionAdmins({ name }),
getCollectionFollowers({ name }),
getCollectionApps({
name: fullName,
collectionId,
sortField,
sortDir,
appFilter,
Expand Down Expand Up @@ -492,19 +494,10 @@ function createCollection({ name, description }) {
});
}

function updateCollectionNameDesc({
originalName,
name,
description,
retagApps,
}) {
const params = {
"retag-apps": retagApps,
};
function updateCollectionNameDesc({ originalName, name, description }) {
return callApi({
endpoint: `/api/communities/${encodeURIComponent(originalName)}`,
method: "PATCH",
params,
body: {
name,
description,
Expand Down Expand Up @@ -546,56 +539,44 @@ function removeCollectionAdmins({ name, adminIds }) {
});
}

function addAppToCollection({ avu, appId }) {
function addAppToCollection({ collectionId, appId }) {
return callApi({
endpoint: `/api/apps/${appId}/communities`,
method: "POST",
body: {
avus: [avu],
community_ids: [collectionId],
},
});
}

function addAppsToCollection({ name, apps, attr }) {
const avu = {
attr,
value: name,
unit: "",
};

return Promise.all(apps.map((appId) => addAppToCollection({ avu, appId })));
function addAppsToCollection({ collectionId, apps }) {
return Promise.all(
apps.map((appId) => addAppToCollection({ collectionId, appId }))
);
}

function removeAppFromCollection({ avu, appId }) {
function removeAppFromCollection({ collectionId, appId }) {
return callApi({
endpoint: `/api/apps/${appId}/communities`,
endpoint: `/api/apps/${appId}/communities/${encodeURIComponent(
collectionId
)}`,
method: "DELETE",
body: {
avus: [avu],
},
});
}

function removeAppsFromCollection({ name, apps, attr }) {
const avu = {
attr,
value: name,
unit: "",
};

function removeAppsFromCollection({ collectionId, apps }) {
return Promise.all(
apps.map((appId) => removeAppFromCollection({ avu, appId }))
apps.map((appId) => removeAppFromCollection({ collectionId, appId }))
);
}

function updateCollectionDetails({
name,
fullName,
collectionId,
oldAdmins,
newAdmins,
oldApps,
newApps,
attr,
}) {
const oldAdminIds = oldAdmins.map((admin) => admin.id);
const newAdminIds = newAdmins.map((admin) => admin.id);
Expand All @@ -622,16 +603,13 @@ function updateCollectionDetails({
);
}
if (addAppIds.length > 0) {
promises.push(
addAppsToCollection({ name: fullName, apps: addAppIds, attr })
);
promises.push(addAppsToCollection({ collectionId, apps: addAppIds }));
}
if (removeAppIds.length > 0) {
promises.push(
removeAppsFromCollection({
name: fullName,
collectionId,
apps: removeAppIds,
attr,
})
);
}
Expand Down
Loading