mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-24 01:18:23 +00:00
Pending Backlog Issues (#10823)
* folder-count-fix * fixed query * fixed app sharing bug * minor css fix for delete group-button * changed delete button color for light mode * profile photo missing in groups * ui fix for alignment * css fix * updated regex for email validation * ui-fix for syncing the ui file with ee * fix for workspace settings page * workspace slug fix * reverted some minor change * minor ui fix * folder-rerender changes
This commit is contained in:
parent
3a8fa29f58
commit
0249102c08
12 changed files with 92 additions and 60 deletions
|
|
@ -401,40 +401,43 @@ class ManageAppUsersComponent extends React.Component {
|
|||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{((this?.props?.isVersionReleased && this?.props?.isPublic) ||
|
||||
window?.public_config?.ENABLE_PRIVATE_APP_EMBED === 'true') && (
|
||||
<div className="tj-app-input">
|
||||
<label className="field-name" data-cy="iframe-link-label">
|
||||
Embedded app link
|
||||
</label>
|
||||
<span className={`tj-text-input justify-content-between ${this.props.darkMode ? 'dark' : ''}`}>
|
||||
<span data-cy="iframe-link">{embeddableLink}</span>
|
||||
<span className="copy-container">
|
||||
<CopyToClipboard text={embeddableLink} onCopy={() => toast.success('Link copied to clipboard')}>
|
||||
<svg
|
||||
className="cursor-pointer"
|
||||
width="17"
|
||||
height="18"
|
||||
viewBox="0 0 17 18"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
data-cy="iframe-link-copy-button"
|
||||
{/* shows embedded app link only for released apps */}
|
||||
{this?.props?.isVersionReleased &&
|
||||
(this?.props?.isPublic || window?.public_config?.ENABLE_PRIVATE_APP_EMBED === 'true') && (
|
||||
<div className="tj-app-input">
|
||||
<label className="field-name" data-cy="iframe-link-label">
|
||||
Embedded app link
|
||||
</label>
|
||||
<span className={`tj-text-input justify-content-between ${this.props.darkMode ? 'dark' : ''}`}>
|
||||
<span data-cy="iframe-link">{embeddableLink}</span>
|
||||
<span className="copy-container">
|
||||
<CopyToClipboard
|
||||
text={embeddableLink}
|
||||
onCopy={() => toast.success('Link copied to clipboard')}
|
||||
>
|
||||
<path
|
||||
d="M9.11154 5.18031H5.88668V4.83302C5.88668 3.29859 7.13059 2.05469 8.66502 2.05469H12.8325C14.3669 2.05469 15.6109 3.29859 15.6109 4.83302V9.00052C15.6109 10.535 14.3669 11.7789 12.8325 11.7789H12.4852V8.554C12.4852 6.69076 10.9748 5.18031 9.11154 5.18031Z"
|
||||
fill="#889096"
|
||||
/>
|
||||
<path
|
||||
d="M8.66502 15.9464H4.49752C2.96309 15.9464 1.71918 14.7025 1.71918 13.168V9.00052C1.71918 7.46609 2.96309 6.22219 4.49752 6.22219H8.66502C10.1994 6.22219 11.4434 7.46609 11.4434 9.00052V13.168C11.4434 14.7025 10.1994 15.9464 8.66502 15.9464Z"
|
||||
fill="#889096"
|
||||
/>
|
||||
</svg>
|
||||
</CopyToClipboard>
|
||||
<svg
|
||||
className="cursor-pointer"
|
||||
width="17"
|
||||
height="18"
|
||||
viewBox="0 0 17 18"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
data-cy="iframe-link-copy-button"
|
||||
>
|
||||
<path
|
||||
d="M9.11154 5.18031H5.88668V4.83302C5.88668 3.29859 7.13059 2.05469 8.66502 2.05469H12.8325C14.3669 2.05469 15.6109 3.29859 15.6109 4.83302V9.00052C15.6109 10.535 14.3669 11.7789 12.8325 11.7789H12.4852V8.554C12.4852 6.69076 10.9748 5.18031 9.11154 5.18031Z"
|
||||
fill="#889096"
|
||||
/>
|
||||
<path
|
||||
d="M8.66502 15.9464H4.49752C2.96309 15.9464 1.71918 14.7025 1.71918 13.168V9.00052C1.71918 7.46609 2.96309 6.22219 4.49752 6.22219H8.66502C10.1994 6.22219 11.4434 7.46609 11.4434 9.00052V13.168C11.4434 14.7025 10.1994 15.9464 8.66502 15.9464Z"
|
||||
fill="#889096"
|
||||
/>
|
||||
</svg>
|
||||
</CopyToClipboard>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
</Modal.Body>
|
||||
|
|
|
|||
|
|
@ -55,10 +55,10 @@ const AppList = (props) => {
|
|||
className={`d-block text-center text-body ${props.darkMode && 'text-white-50'}`}
|
||||
data-cy="empty-folder-text"
|
||||
>
|
||||
{/* removed this error message display for now -> as it was leading to multiple message being shown in the UI*/}
|
||||
{/* {props.currentFolder?.count == 0
|
||||
? t('homePage.thisFolderIsEmpty', 'This folder is empty')
|
||||
: t('homePage.nonAccessibleFolderApps', 'You do not have access to any applications in this folder.')} */}
|
||||
{props.currentFolder?.count == 0 &&
|
||||
props.apps?.length == 0 &&
|
||||
props.appSearchKey == '' &&
|
||||
t('homePage.thisFolderIsEmpty', 'This folder is empty')}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ export const Folders = function Folders({
|
|||
canDeleteFolder,
|
||||
canCreateApp,
|
||||
darkMode,
|
||||
searchedAppCount,
|
||||
}) {
|
||||
const [isLoading, setLoadingStatus] = useState(foldersLoading);
|
||||
const [showInput, setShowInput] = useState(false);
|
||||
|
|
@ -40,11 +41,14 @@ export const Folders = function Folders({
|
|||
const [activeFolder, setActiveFolder] = useState(currentFolder || {});
|
||||
const [filteredData, setFilteredData] = useState(folders);
|
||||
const [errorText, setErrorText] = useState('');
|
||||
const [activeFolderAppCount, setActiveFolderAppCount] = useState(activeFolder.count);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { t } = useTranslation();
|
||||
const { updateSidebarNAV } = useContext(BreadCrumbContext);
|
||||
|
||||
useEffect(() => {
|
||||
setActiveFolderAppCount(searchedAppCount);
|
||||
}, [searchedAppCount]);
|
||||
useEffect(() => {
|
||||
setLoadingStatus(foldersLoading);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
|
@ -107,6 +111,7 @@ export const Folders = function Folders({
|
|||
updateSidebarNAV(folder?.name ?? 'All apps');
|
||||
//update the url query parameter with folder name
|
||||
updateFolderQuery(folder?.name);
|
||||
setActiveFolderAppCount(folder.count);
|
||||
}
|
||||
|
||||
function updateFolderQuery(name) {
|
||||
|
|
@ -311,7 +316,11 @@ export const Folders = function Folders({
|
|||
className="flex-grow-1 tj-folder-list tj-text-xsm"
|
||||
data-cy={`${folder.name.toLowerCase().replace(/\s+/g, '-')}-name`}
|
||||
>
|
||||
{`${folder.name}${folder.count > 0 ? ` (${folder.count})` : ''}`}
|
||||
{folder.id === activeFolder.id ? (
|
||||
<span>{`${folder.name}${folder.count > 0 ? ` (${activeFolderAppCount})` : ''}`}</span>
|
||||
) : (
|
||||
<span>{`${folder.name}${folder.count > 0 ? ` (${folder.count})` : ''}`}</span>
|
||||
)}
|
||||
</div>
|
||||
</ToolTip>
|
||||
{(canDeleteFolder || canUpdateFolder) && (
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ class HomePageComponent extends React.Component {
|
|||
this.setState({
|
||||
apps: data.apps,
|
||||
meta: { ...this.state.meta, ...data.meta },
|
||||
searchedAppCount: appSearchKey ? data.apps.length : this.state.currentFolder.count,
|
||||
isLoading: false,
|
||||
})
|
||||
);
|
||||
|
|
@ -842,6 +843,7 @@ class HomePageComponent extends React.Component {
|
|||
canUpdateFolder={this.canUpdateFolder()}
|
||||
darkMode={this.props.darkMode}
|
||||
canCreateApp={this.canCreateApp()}
|
||||
searchedAppCount={this.state.searchedAppCount}
|
||||
/>
|
||||
<OrganizationList />
|
||||
</div>
|
||||
|
|
@ -900,7 +902,7 @@ class HomePageComponent extends React.Component {
|
|||
canCreateApp={this.canCreateApp}
|
||||
/>
|
||||
)}
|
||||
{!isLoading && meta.total_count === 0 && appSearchKey && (
|
||||
{!isLoading && apps?.length === 0 && appSearchKey && (
|
||||
<div>
|
||||
<span className={`d-block text-center text-body pt-5 ${this.props.darkMode && 'text-white-50'}`}>
|
||||
{this.props.t('homePage.noApplicationFound', 'No Applications found')}
|
||||
|
|
@ -921,6 +923,7 @@ class HomePageComponent extends React.Component {
|
|||
darkMode={this.props.darkMode}
|
||||
appActionModal={this.appActionModal}
|
||||
removeAppFromFolder={this.removeAppFromFolder}
|
||||
appSearchKey={this.state.appSearchKey}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ import { SearchBox } from '@/_components/SearchBox';
|
|||
import EditRoleErrorModal from '@/ManageGroupPermissionsV2/ErrorModal/ErrorModal';
|
||||
import ChangeRoleModal from '@/ManageGroupPermissionResourcesV2/ChangeRoleModal';
|
||||
import { ToolTip } from '@/_components/ToolTip';
|
||||
import Avatar from '@/_ui/Avatar';
|
||||
|
||||
class ManageGroupPermissionResourcesComponent extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
|
@ -339,7 +341,6 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
|
|||
this.setState({ isChangeRoleModalOpen: true, updatingUserRole: updatingUser });
|
||||
|
||||
showChangeRoleModalMessage = () => {
|
||||
console.log('called');
|
||||
this.setState({ showRoleEditMessage: true });
|
||||
};
|
||||
|
||||
|
|
@ -435,7 +436,6 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
|
|||
autoRoleChangeModalList,
|
||||
autoRoleChangeMessageType,
|
||||
} = this.state;
|
||||
|
||||
const isBasicPlan = false;
|
||||
const isPaidPlan = false;
|
||||
|
||||
|
|
@ -737,11 +737,16 @@ class ManageGroupPermissionResourcesComponent extends React.Component {
|
|||
key={user.id}
|
||||
className="manage-group-users-row"
|
||||
data-cy={`${String(user.email).toLowerCase().replace(/\s+/g, '-')}-user-row`}
|
||||
style={{ alignItems: 'center' }}
|
||||
>
|
||||
<p className="tj-text-sm d-flex align-items-center">
|
||||
<div className="name-avatar">
|
||||
{`${user?.firstName?.[0] ?? ''} ${user?.lastName?.[0] ?? ''}`}
|
||||
</div>
|
||||
<Avatar
|
||||
className="name-avatar"
|
||||
avatarId={user.avatarId}
|
||||
text={`${user.first_name ? user.first_name[0] : ''}${
|
||||
user.last_name ? user.last_name[0] : ''
|
||||
}`}
|
||||
/>
|
||||
<span>{`${user?.firstName ?? ''} ${user?.lastName ?? ''}`}</span>
|
||||
</p>
|
||||
<p className="tj-text-sm d-flex align-items-center" style={{ paddingLeft: '12px' }}>
|
||||
|
|
|
|||
|
|
@ -42,19 +42,20 @@ export function OrganizationSettings(props) {
|
|||
if (selectedTabFromRoute === 'workspace-settings') {
|
||||
// No Sub routes added loading first one
|
||||
setSelectedTab(admin ? workspaceSettingsLinks[0].id : 'workspacevariables');
|
||||
navigate(admin ? workspaceSettingsLinks[0].route : 'workspace-variables');
|
||||
} else {
|
||||
const selectedWorkspaceSetting = workspaceSettingsLinks?.find((m) => m.id === selectedTabFromRoute);
|
||||
updateSidebarNAV(selectedWorkspaceSetting?.name || '');
|
||||
setSelectedTab(getMenuFromRoute(selectedTabFromRoute)?.id);
|
||||
}
|
||||
|
||||
return () => subscription.unsubscribe();
|
||||
}, [authenticationService.currentSessionValue?.admin]);
|
||||
|
||||
useEffect(() => {
|
||||
const menu = workspaceSettingsLinks?.find((m) => m.id === selectedTab);
|
||||
updateSidebarNAV(menu?.name || '');
|
||||
navigate(menu?.route || '');
|
||||
}, [selectedTab]);
|
||||
}, [admin, location.pathname]);
|
||||
|
||||
const handleClick = (data) => {
|
||||
setSelectedTab(data.id);
|
||||
updateSidebarNAV(data?.name || '');
|
||||
};
|
||||
return (
|
||||
<Layout switchDarkMode={props.switchDarkMode} darkMode={props.darkMode}>
|
||||
<div className="wrapper organization-settings-page">
|
||||
|
|
@ -67,6 +68,7 @@ export function OrganizationSettings(props) {
|
|||
<Wrapper key={index}>
|
||||
<Link
|
||||
key={index}
|
||||
to={item.route}
|
||||
style={{
|
||||
textDecoration: 'none',
|
||||
border: 'none',
|
||||
|
|
@ -79,7 +81,7 @@ export function OrganizationSettings(props) {
|
|||
className="workspace-settings-nav-items"
|
||||
key={index}
|
||||
onClick={() => {
|
||||
setSelectedTab(item.id);
|
||||
handleClick(item);
|
||||
}}
|
||||
selectedItem={selectedTab == item.id}
|
||||
renderBadgeForItems={[]}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ export const CreateOrganization = ({ showCreateOrg, setShowCreateOrg }) => {
|
|||
};
|
||||
|
||||
const handleInputChange = async (value, field) => {
|
||||
const trimmedValue = value?.trim();
|
||||
if (field === 'slug') {
|
||||
setSlug({
|
||||
...slug,
|
||||
|
|
@ -83,7 +84,7 @@ export const CreateOrganization = ({ showCreateOrg, setShowCreateOrg }) => {
|
|||
if (error?.status === true) {
|
||||
try {
|
||||
await organizationService.checkWorkspaceUniqueness(
|
||||
field === 'name' ? value : null,
|
||||
field === 'name' ? trimmedValue : null,
|
||||
field === 'slug' ? value : null
|
||||
);
|
||||
} catch (errResponse) {
|
||||
|
|
|
|||
|
|
@ -578,7 +578,7 @@ export function validateDates({ validationObject, widgetValue, currentState, cus
|
|||
|
||||
export function validateEmail(email) {
|
||||
const emailRegex =
|
||||
/^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
|
||||
/^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[a-zA-Z]{2,})$/i;
|
||||
return emailRegex.test(email);
|
||||
}
|
||||
|
||||
|
|
@ -1099,9 +1099,9 @@ export const validateName = (
|
|||
checkReservedWords = false,
|
||||
allowAllCases = false
|
||||
) => {
|
||||
const newName = name.trim();
|
||||
const newName = name;
|
||||
let errorMsg = '';
|
||||
if (emptyCheck && !newName) {
|
||||
if (emptyCheck && (!newName || newName.trim().length === 0)) {
|
||||
errorMsg = `${nameType} can't be empty`;
|
||||
showError &&
|
||||
toast.error(errorMsg, {
|
||||
|
|
|
|||
|
|
@ -9841,7 +9841,7 @@ tbody {
|
|||
.manage-group-users-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: baseline;
|
||||
align-items: center;
|
||||
padding: 12px 6px;
|
||||
width: 612px !important;
|
||||
height: 64px;
|
||||
|
|
@ -10567,7 +10567,14 @@ tbody {
|
|||
}
|
||||
|
||||
.disable {
|
||||
color: var(--slate7);
|
||||
color: var(--slate9);
|
||||
}
|
||||
.disable {
|
||||
color: var(--slate9);
|
||||
|
||||
&.dark-theme {
|
||||
color: var(--slate11);
|
||||
}
|
||||
}
|
||||
|
||||
&__danger {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
.query-manager-border-color{
|
||||
input.form-control,
|
||||
textarea,
|
||||
.input-control {
|
||||
|
|
@ -51,7 +52,7 @@ textarea,
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
.empty-key-value {
|
||||
border-radius: 6px;
|
||||
padding: 10px;
|
||||
|
|
|
|||
|
|
@ -234,6 +234,7 @@ export function getUserInGroupQuery(
|
|||
'users.firstName',
|
||||
'users.lastName',
|
||||
'users.email',
|
||||
'users.avatarId',
|
||||
'userRole.id',
|
||||
'role.name',
|
||||
'organizationUsers.status',
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ export class FoldersService {
|
|||
.innerJoin('folderApp.app', 'app', 'folderApp.folderId = :id', {
|
||||
id: folder.id,
|
||||
})
|
||||
.where('app.name LIKE :name', { name: `%${searchKey}%` })
|
||||
.where('LOWER(app.name) LIKE :name', { name: `%${(searchKey ?? '').toLowerCase()}%` })
|
||||
.getMany();
|
||||
|
||||
const userPermission = await this.abilityService.resourceActionsPermission(user, {
|
||||
|
|
|
|||
Loading…
Reference in a new issue