Browse Source

Merge pull request #655 from colinin/Switch-Ui-Setup-Syntax

feat: components switch to setup syntax
pull/712/head
yx lin 3 years ago
committed by GitHub
parent
commit
22fd445b6e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      apps/vue/src/api/auditing/auditLog.ts
  2. 8
      apps/vue/src/api/identity/securityLog.ts
  3. 58
      apps/vue/src/components/MultiTenancyBox/src/MultiTenancyBox.vue
  4. 119
      apps/vue/src/components/MultiTenancyBox/src/MultiTenancyModal.vue
  5. 180
      apps/vue/src/components/SettingManagement/src/SettingForm.vue
  6. 9
      apps/vue/src/utils/cache/persistent.ts
  7. 4
      apps/vue/src/utils/dateUtil.ts
  8. 194
      apps/vue/src/views/account/center/Cloud.vue
  9. 1
      apps/vue/src/views/account/center/FileList.vue
  10. 100
      apps/vue/src/views/account/center/index.vue
  11. 37
      apps/vue/src/views/account/setting/AccountBind.vue
  12. 171
      apps/vue/src/views/account/setting/BaseSetting.vue
  13. 75
      apps/vue/src/views/account/setting/MsgNotify.vue
  14. 122
      apps/vue/src/views/account/setting/SecureSetting.vue
  15. 63
      apps/vue/src/views/account/setting/index.vue
  16. 164
      apps/vue/src/views/auditing/components/AuditLogModal.vue
  17. 105
      apps/vue/src/views/auditing/components/AuditLogTable.vue
  18. 2
      apps/vue/src/views/caching-management/cache/datas/ModalData.ts
  19. 78
      apps/vue/src/views/feature/src/FeatureModal.vue
  20. 159
      apps/vue/src/views/identity-server/api-resources/components/ApiResourceModal.vue
  21. 65
      apps/vue/src/views/identity-server/api-resources/components/ApiResourceScope.vue
  22. 89
      apps/vue/src/views/identity-server/api-resources/components/ApiResourceSecret.vue
  23. 122
      apps/vue/src/views/identity-server/api-resources/components/ApiResourceTable.vue
  24. 4
      apps/vue/src/views/identity-server/api-resources/datas/TableData.ts
  25. 17
      apps/vue/src/views/identity-server/api-resources/hooks/useModal.ts
  26. 135
      apps/vue/src/views/identity-server/api-scopes/components/ApiScopeModal.vue
  27. 128
      apps/vue/src/views/identity-server/api-scopes/components/ApiScopeTable.vue
  28. 32
      apps/vue/src/views/identity-server/api-scopes/datas/TableData.ts
  29. 17
      apps/vue/src/views/identity-server/api-scopes/hooks/useModal.ts
  30. 81
      apps/vue/src/views/identity-server/clients/components/ClientApiResource.vue
  31. 79
      apps/vue/src/views/identity-server/clients/components/ClientCallback.vue
  32. 130
      apps/vue/src/views/identity-server/clients/components/ClientClaim.vue
  33. 278
      apps/vue/src/views/identity-server/clients/components/ClientClone.vue
  34. 77
      apps/vue/src/views/identity-server/clients/components/ClientCorsOrigins.vue
  35. 87
      apps/vue/src/views/identity-server/clients/components/ClientGrantType.vue
  36. 90
      apps/vue/src/views/identity-server/clients/components/ClientIdentityProvider.vue
  37. 83
      apps/vue/src/views/identity-server/clients/components/ClientIdentityResource.vue
  38. 79
      apps/vue/src/views/identity-server/clients/components/ClientLogoutRedirectUris.vue
  39. 203
      apps/vue/src/views/identity-server/clients/components/ClientModal.vue
  40. 113
      apps/vue/src/views/identity-server/clients/components/ClientProperties.vue
  41. 206
      apps/vue/src/views/identity-server/clients/components/ClientSecret.vue
  42. 155
      apps/vue/src/views/identity-server/clients/components/ClientTable.vue
  43. 181
      apps/vue/src/views/identity-server/clients/components/DynamicForm.vue
  44. 59
      apps/vue/src/views/identity-server/clients/components/Resources.vue
  45. 32
      apps/vue/src/views/identity-server/clients/hooks/useModal.ts
  46. 86
      apps/vue/src/views/identity-server/components/Properties.vue
  47. 87
      apps/vue/src/views/identity-server/components/UserClaim.vue
  48. 140
      apps/vue/src/views/identity-server/identity-resources/components/IdentityResourceModal.vue
  49. 128
      apps/vue/src/views/identity-server/identity-resources/components/IdentityResourceTable.vue
  50. 28
      apps/vue/src/views/identity-server/identity-resources/datas/TableData.ts
  51. 32
      apps/vue/src/views/identity-server/identity-resources/hooks/useModal.ts
  52. 20
      apps/vue/src/views/identity-server/persisted-grants/components/ModalData.ts
  53. 72
      apps/vue/src/views/identity-server/persisted-grants/components/PersistedGrantModal.vue
  54. 98
      apps/vue/src/views/identity-server/persisted-grants/components/PersistedGrantTable.vue
  55. 66
      apps/vue/src/views/identity/claim-types/components/ClaimModal.vue
  56. 48
      apps/vue/src/views/identity/claim-types/components/ClaimTable.vue
  57. 9
      apps/vue/src/views/identity/claim-types/hooks/useClaimTable.ts
  58. 2
      apps/vue/src/views/identity/components/ClaimModal.vue
  59. 209
      apps/vue/src/views/identity/components/MenuModal.vue
  60. 188
      apps/vue/src/views/identity/organization-units/components/MemberModal.vue
  61. 63
      apps/vue/src/views/identity/organization-units/components/MemberTable.vue
  62. 38
      apps/vue/src/views/identity/organization-units/components/OrganizationUnitPage.vue
  63. 47
      apps/vue/src/views/identity/organization-units/components/OrganizationUnitTree.vue
  64. 174
      apps/vue/src/views/identity/organization-units/components/RoleModal.vue
  65. 63
      apps/vue/src/views/identity/organization-units/components/RoleTable.vue
  66. 14
      apps/vue/src/views/identity/organization-units/hooks/useMemberTable.ts
  67. 6
      apps/vue/src/views/identity/organization-units/hooks/useOuTree.ts
  68. 12
      apps/vue/src/views/identity/organization-units/hooks/useRoleTable.ts
  69. 1
      apps/vue/src/views/identity/organization-units/index.vue
  70. 61
      apps/vue/src/views/identity/role/components/ClaimModal.vue
  71. 68
      apps/vue/src/views/identity/role/components/RoleModal.vue
  72. 115
      apps/vue/src/views/identity/role/components/RoleTable.vue
  73. 15
      apps/vue/src/views/identity/role/hooks/useClaim.ts
  74. 7
      apps/vue/src/views/identity/role/hooks/useRoleTable.ts
  75. 90
      apps/vue/src/views/identity/security-logs/components/SecurityLogTable.vue
  76. 45
      apps/vue/src/views/identity/user/components/LockModal.vue
  77. 75
      apps/vue/src/views/identity/user/components/PasswordModal.vue
  78. 91
      apps/vue/src/views/identity/user/components/UserModal.vue
  79. 141
      apps/vue/src/views/identity/user/components/UserTable.vue
  80. 14
      apps/vue/src/views/identity/user/hooks/useUserForm.ts
  81. 14
      apps/vue/src/views/identity/user/hooks/useUserTable.ts
  82. 97
      apps/vue/src/views/localization/languages/components/LanguageTable.vue
  83. 95
      apps/vue/src/views/localization/resources/components/ResourceTable.vue
  84. 261
      apps/vue/src/views/localization/texts/components/TextModal.vue
  85. 112
      apps/vue/src/views/localization/texts/components/TextTable.vue
  86. 156
      apps/vue/src/views/oss-management/containers/components/ContainerTable.vue
  87. 4
      apps/vue/src/views/oss-management/objects/components/FileList.vue
  88. 81
      apps/vue/src/views/oss-management/objects/components/OssFolderModal.vue
  89. 75
      apps/vue/src/views/oss-management/objects/components/OssManagePage.vue
  90. 47
      apps/vue/src/views/oss-management/objects/components/OssPreviewModal.vue
  91. 303
      apps/vue/src/views/oss-management/objects/components/OssUploadModal.vue
  92. 119
      apps/vue/src/views/platform/dataDic/components/DataItemModal.vue
  93. 176
      apps/vue/src/views/platform/dataDic/components/DataItemTable.vue
  94. 108
      apps/vue/src/views/platform/dataDic/components/DataModal.vue
  95. 162
      apps/vue/src/views/platform/dataDic/components/DataTree.vue
  96. 36
      apps/vue/src/views/platform/dataDic/index.vue
  97. 94
      apps/vue/src/views/platform/layout/components/LayoutModal.vue
  98. 105
      apps/vue/src/views/platform/layout/components/LayoutTable.vue
  99. 77
      apps/vue/src/views/platform/menu/components/MenuDrawer.vue
  100. 140
      apps/vue/src/views/platform/menu/components/MenuTable.vue

4
apps/vue/src/api/auditing/auditLog.ts

@ -12,9 +12,7 @@ export const deleteById = (id: string) => {
controller: Api.Controller,
action: 'DeleteAsync',
params: {
input: {
id: id,
},
id: id,
},
});
};

8
apps/vue/src/api/identity/securityLog.ts

@ -12,9 +12,7 @@ export const deleteById = (id: string) => {
controller: Api.Controller,
action: 'DeleteAsync',
params: {
input: {
id: id,
},
id: id,
},
});
};
@ -25,9 +23,7 @@ export const getById = (id: string) => {
controller: Api.Controller,
action: 'GetAsync',
params: {
input: {
id: id,
},
id: id,
},
});
};

58
apps/vue/src/components/MultiTenancyBox/src/MultiTenancyBox.vue

@ -16,50 +16,28 @@
</div>
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue';
import { Button, Form, Input } from 'ant-design-vue';
import { Input as BInput } from '/@/components/Input';
import { BasicModal, useModal } from '/@/components/Modal';
<script lang="ts" setup>
import { computed } from 'vue';
import { Button, Input } from 'ant-design-vue';
import { useModal } from '/@/components/Modal';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useAbpStoreWithOut } from '/@/store/modules/abp';
import MultiTenancyModal from './MultiTenancyModal.vue';
export default defineComponent({
name: 'MultiTenancyBox',
components: {
BasicModal,
Button,
Form,
FormItem: Form.Item,
BInput,
InputSearch: Input.Search,
MultiTenancyModal,
},
setup() {
const { L } = useLocalization('AbpUiMultiTenancy');
const [registerModal, { openModal }] = useModal();
const multiTenancyEnabled = computed(() => {
const abpStore = useAbpStoreWithOut();
return abpStore.getApplication.multiTenancy.isEnabled;
});
const currentTenant = computed(() => {
const abpStore = useAbpStoreWithOut();
return abpStore.getApplication.currentTenant;
});
function handleSwitchTenant() {
openModal(true, currentTenant.value.name);
}
const InputSearch = Input.Search;
return {
L,
multiTenancyEnabled,
currentTenant,
registerModal,
handleSwitchTenant,
};
},
const { L } = useLocalization('AbpUiMultiTenancy');
const [registerModal, { openModal }] = useModal();
const multiTenancyEnabled = computed(() => {
const abpStore = useAbpStoreWithOut();
return abpStore.getApplication.multiTenancy.isEnabled;
});
const currentTenant = computed(() => {
const abpStore = useAbpStoreWithOut();
return abpStore.getApplication.currentTenant;
});
function handleSwitchTenant() {
openModal(true, currentTenant.value.name);
}
</script>

119
apps/vue/src/components/MultiTenancyBox/src/MultiTenancyModal.vue

@ -14,8 +14,8 @@
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, nextTick } from 'vue';
<script lang="ts" setup>
import { nextTick, inject } from 'vue';
import { BasicForm, useForm } from '/@/components/Form';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { findTenantByName } from '/@/api/multi-tenancy/tenants';
@ -24,74 +24,57 @@
import { useAbpStoreWithOut } from '/@/store/modules/abp';
import { useGlobSetting } from '/@/hooks/setting';
export default defineComponent({
name: 'MultiTenancyModal',
components: { BasicForm, BasicModal },
setup() {
const globSetting = useGlobSetting();
const { L } = useLocalization('AbpUiMultiTenancy');
const { createMessage } = useMessage();
const [registerForm, { validate, setFieldsValue }] = useForm({
showActionButtonGroup: false,
layout: 'vertical',
schemas: [
{
field: 'name',
label: L('SwitchTenantHint'),
component: 'Input',
colProps: { span: 24 },
},
],
});
const [registerModal, { closeModal, changeLoading }] = useModalInner((name) => {
nextTick(() => {
setFieldsValue({
name: name,
});
});
const cookies = inject<any>('$cookies');
const globSetting = useGlobSetting();
const { L } = useLocalization('AbpUiMultiTenancy');
const { createMessage } = useMessage();
const [registerForm, { validate, setFieldsValue }] = useForm({
showActionButtonGroup: false,
layout: 'vertical',
schemas: [
{
field: 'name',
label: L('SwitchTenantHint'),
component: 'Input',
colProps: { span: 24 },
},
],
});
const [registerModal, { closeModal, changeLoading }] = useModalInner((name) => {
nextTick(() => {
setFieldsValue({
name: name,
});
});
});
return {
L,
registerForm,
registerModal,
validate,
createMessage,
closeModal,
globSetting,
changeLoading,
};
},
methods: {
switchToTenant() {
this.validate().then((input) => {
this.changeLoading(true);
const abpStore = useAbpStoreWithOut();
if (!input.name) {
this.$cookies.remove(this.globSetting.multiTenantKey);
} else {
findTenantByName(input.name).then((result) => {
if (!result.success || !result.tenantId) {
this.createMessage.warn(this.L('GivenTenantIsNotExist', [input.name]));
return;
}
if (!result.isActive) {
this.createMessage.warn(this.L('GivenTenantIsNotAvailable', [input.name]));
return;
}
function switchToTenant() {
validate().then((input) => {
changeLoading(true);
const abpStore = useAbpStoreWithOut();
if (!input.name) {
cookies?.remove(globSetting.multiTenantKey);
} else {
findTenantByName(input.name).then((result) => {
if (!result.success || !result.tenantId) {
createMessage.warn(L('GivenTenantIsNotExist', [input.name]));
return;
}
this.$cookies.set(this.globSetting.multiTenantKey, result.tenantId);
}).finally(() => this.changeLoading(false));
if (!result.isActive) {
createMessage.warn(L('GivenTenantIsNotAvailable', [input.name]));
return;
}
//
setTimeout(() => {
abpStore.initlizeAbpApplication()
.then(this.closeModal)
.finally(() => this.changeLoading(false));
}, 100);
});
},
}
})
cookies?.set(globSetting.multiTenantKey, result.tenantId);
}).finally(() => changeLoading(false));
}
//
setTimeout(() => {
abpStore.initlizeAbpApplication()
.then(closeModal)
.finally(() => changeLoading(false));
}, 100);
});
}
</script>

180
apps/vue/src/components/SettingManagement/src/SettingForm.vue

@ -81,7 +81,7 @@
</TabPane>
</Tabs>
<FormItem style="margin-top: 20px">
<a-button
<Button
v-if="updateSetting.settings.length > 0"
type="primary"
style="width: 150px"
@ -90,19 +90,20 @@
@click="handleSubmit"
>
{{ sumbitButtonTitle }}
</a-button>
</Button>
</FormItem>
</Form>
</Card>
</template>
<script lang="ts">
<script lang="ts" setup>
import dayjs from 'dayjs';
import { computed, defineComponent, ref, toRaw } from 'vue';
import { computed, ref, toRaw } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useTabsStyle } from '/@/hooks/component/useStyles';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import {
Button,
Card,
Checkbox,
Tabs,
@ -110,15 +111,20 @@
Form,
Input,
Select,
Row,
Col,
DatePicker,
} from 'ant-design-vue';
import { Input as BInput } from '/@/components/Input';
import { formatToDate } from '/@/utils/dateUtil';
import { SettingGroup, SettingsUpdate } from '/@/api/settings/model/settingModel';
const props = {
const CollapsePanel = Collapse.Panel;
const FormItem = Form.Item;
const SelectOption = Select.Option;
const TabPane = Tabs.TabPane;
const Password = Input.Password;
const emits = defineEmits(['change']);
const props = defineProps({
settingGroups: {
type: Array as PropType<Array<SettingGroup>>,
required: true,
@ -131,110 +137,72 @@
type: String as PropType<'left' | 'right' | 'top' | 'bottom'>,
default: 'top',
},
} as const; // props see: https://blog.csdn.net/q535999731/article/details/109578885
});
export default defineComponent({
components: {
Card,
Checkbox,
Collapse: Collapse,
CollapsePanel: Collapse.Panel,
DatePicker,
Form: Form,
FormItem: Form.Item,
BInput,
Select,
SelectOption: Select.Option,
Tabs: Tabs,
TabPane: Tabs.TabPane,
Password: Input.Password,
Row,
Col,
},
props,
emits: ['change'],
setup(props, { emit }) {
const { L } = useLocalization('AbpSettingManagement');
const activeTabKey = ref(0);
const saving = ref(false);
const updateSetting = ref(new SettingsUpdate());
const { createMessage } = useMessage();
const { success } = createMessage;
const { L } = useLocalization('AbpSettingManagement');
const activeTabKey = ref(0);
const saving = ref(false);
const updateSetting = ref(new SettingsUpdate());
const { createMessage } = useMessage();
const { success } = createMessage;
const tabsStyle = useTabsStyle(
props.tabPosition,
{},
{
top: props.tabPosition === 'top' ? '80px' : '0'
});
const sumbitButtonTitle = computed(() => {
if (saving.value) {
return L('Save');
}
return L('Save');
});
const expandedCollapseKeys = computed(() => {
return (group) => {
const keys = group.settings.map((s) => {
return s.displayName;
});
return keys;
};
const tabsStyle = useTabsStyle(
props.tabPosition,
{},
{
top: props.tabPosition === 'top' ? '80px' : '0'
});
const sumbitButtonTitle = computed(() => {
if (saving.value) {
return L('Save');
}
return L('Save');
});
const expandedCollapseKeys = computed(() => {
return (group) => {
const keys = group.settings.map((s) => {
return s.displayName;
});
return keys;
};
});
function handleCheckChange(setting) {
if (setting.value === 'true') {
setting.value = 'false';
} else {
setting.value = 'true';
}
handleValueChange(setting);
}
function handleDateChange(e, setting) {
setting.value = dayjs.isDayjs(e) ? formatToDate(e) : '';
handleValueChange(setting);
}
function handleCheckChange(setting) {
if (setting.value === 'true') {
setting.value = 'false';
} else {
setting.value = 'true';
}
handleValueChange(setting);
}
function handleValueChange(setting) {
const index = updateSetting.value.settings.findIndex((s) => s.name === setting.name);
if (index >= 0) {
updateSetting.value.settings[index].value = setting.value;
} else {
updateSetting.value.settings.push({
name: setting.name,
value: setting.value,
});
}
}
function handleDateChange(e, setting) {
setting.value = dayjs.isDayjs(e) ? formatToDate(e) : '';
handleValueChange(setting);
}
function handleSubmit() {
saving.value = true;
props
.saveApi(toRaw(updateSetting.value))
.then(() => {
success(L('SuccessfullySaved'));
emit('change', toRaw(updateSetting.value));
})
.finally(() => {
saving.value = false;
});
}
function handleValueChange(setting) {
const index = updateSetting.value.settings.findIndex((s) => s.name === setting.name);
if (index >= 0) {
updateSetting.value.settings[index].value = setting.value;
} else {
updateSetting.value.settings.push({
name: setting.name,
value: setting.value,
});
}
}
return {
L,
dayjs,
saving,
tabsStyle,
activeTabKey,
updateSetting,
sumbitButtonTitle,
expandedCollapseKeys,
handleCheckChange,
handleDateChange,
handleValueChange,
handleSubmit,
};
},
});
function handleSubmit() {
saving.value = true;
props
.saveApi(toRaw(updateSetting.value))
.then(() => {
success(L('SuccessfullySaved'));
emits('change', toRaw(updateSetting.value));
})
.finally(() => {
saving.value = false;
});
}
</script>

9
apps/vue/src/utils/cache/persistent.ts

@ -6,7 +6,6 @@ import { createLocalStorage, createSessionStorage } from '/@/utils/cache';
import { Memory } from './memory';
import {
TOKEN_KEY,
ABP_TENANT_KEY,
USER_INFO_KEY,
ROLES_KEY,
LOCK_INFO_KEY,
@ -21,7 +20,6 @@ import { pick, omit } from 'lodash-es';
interface BasicStore {
[TOKEN_KEY]: string | number | null | undefined;
[ABP_TENANT_KEY]: string;
[USER_INFO_KEY]: UserInfo;
[ROLES_KEY]: string[];
[LOCK_INFO_KEY]: LockInfo;
@ -51,13 +49,6 @@ function initPersistentMemory() {
}
export class Persistent {
static setTenant(value: any) {
ls.set(ABP_TENANT_KEY, value);
}
static getTenant() {
return ls.get(ABP_TENANT_KEY);
}
static getLocal<T>(key: LocalKeys) {
return localMemory.get(key)?.value as Nullable<T>;

4
apps/vue/src/utils/dateUtil.ts

@ -7,14 +7,14 @@ const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
const DATE_FORMAT = 'YYYY-MM-DD';
export function formatToDateTime(
date: string | dayjs.Dayjs | undefined = undefined,
date: string | Date | dayjs.Dayjs | undefined = undefined,
format = DATE_TIME_FORMAT,
): string {
return dayjs(date).format(format);
}
export function formatToDate(
date: string | dayjs.Dayjs | undefined = undefined,
date: string | Date | dayjs.Dayjs | undefined = undefined,
format = DATE_FORMAT,
): string {
return dayjs(date).format(format);

194
apps/vue/src/views/account/center/Cloud.vue

@ -15,7 +15,7 @@
</CardGrid>
<CardGrid style="width: 75%">
<component
:is="switchComponent.name"
:is="componentsRef[switchComponent.name]"
:select-group="switchComponent.group"
:select-path="switchComponent.path"
:delete-enabled="deleteEnabled"
@ -26,8 +26,8 @@
</div>
</template>
<script lang="ts">
import { computed, defineComponent, ref } from 'vue';
<script lang="ts" setup>
import { computed, ref, shallowRef } from 'vue';
import { Card, Tree } from 'ant-design-vue';
import { TreeDataItem } from 'ant-design-vue/es/tree/Tree';
import { useLocalization } from '/@/hooks/abp/useLocalization';
@ -36,6 +36,15 @@
import FileList from './FileList.vue';
import ShareList from './ShareList.vue';
const componentsRef = shallowRef({
'FileList': FileList,
'ShareList': ShareList,
});
const CardGrid = Card.Grid;
const CardMeta = Card.Meta;
const DirectoryTree = Tree.DirectoryTree;
interface IComponent {
name: string;
group: string;
@ -43,111 +52,88 @@
dataRef: any;
}
export default defineComponent({
components: {
Card,
CardGrid: Card.Grid,
CardMeta: Card.Meta,
DirectoryTree: Tree.DirectoryTree,
FileList,
ShareList,
const { hasPermission } = usePermission();
const { L } = useLocalization(['AbpOssManagement', 'AbpUi']);
const folderTreeRef = ref<{ [key: string]: TreeDataItem }>({
private: {
key: 'private',
group: 'private',
title: L('MyDocument'),
path: '/',
children: [],
},
setup() {
const { hasPermission } = usePermission();
const { L } = useLocalization(['AbpOssManagement', 'AbpUi']);
const folderTreeRef = ref<{ [key: string]: TreeDataItem }>({
private: {
key: 'private',
group: 'private',
title: L('MyDocument'),
path: '/',
children: [],
},
public: {
key: 'public',
group: 'public',
title: L('PublicDocument'),
path: '/',
children: [],
},
share: {
key: 'share',
group: 'share',
title: L('MyShare'),
path: '/',
children: [],
},
});
const folderTree = computed(() => {
return Object.keys(folderTreeRef.value).map((key) => folderTreeRef.value[key]);
});
const switchComponent = ref<IComponent>({
name: 'FileList',
group: '',
path: '/',
dataRef: {},
});
const deleteEnabled = computed(() => {
switch (switchComponent.value.group) {
case 'private':
case 'share':
return true;
case 'public':
return hasPermission('AbpOssManagement.OssObject.Delete');
default:
return false;
}
});
const expandedKeys = ref<string[]>([]);
function fetchFolders(keys) {
expandedKeys.value = keys;
}
public: {
key: 'public',
group: 'public',
title: L('PublicDocument'),
path: '/',
children: [],
},
share: {
key: 'share',
group: 'share',
title: L('MyShare'),
path: '/',
children: [],
},
});
const folderTree = computed(() => {
return Object.keys(folderTreeRef.value).map((key) => folderTreeRef.value[key]);
});
const switchComponent = ref<IComponent>({
name: 'FileList',
group: '',
path: '/',
dataRef: {},
});
const deleteEnabled = computed(() => {
switch (switchComponent.value.group) {
case 'private':
case 'share':
return true;
case 'public':
return hasPermission('AbpOssManagement.OssObject.Delete');
default:
return false;
}
});
const expandedKeys = ref<string[]>([]);
function handleSelectFolder(_, e) {
switch (e.node.dataRef.group) {
case 'private':
case 'public':
switchComponent.value = {
name: 'FileList',
group: e.node.dataRef.group,
path: e.node.dataRef.path,
dataRef: e.node.dataRef,
};
break;
case 'share':
switchComponent.value = {
name: 'ShareList',
group: e.node.dataRef.group,
path: e.node.dataRef.path,
dataRef: e.node.dataRef,
};
break;
}
}
function fetchFolders(keys) {
expandedKeys.value = keys;
}
function handleAppendFolder(folders: OssObject[]) {
switchComponent.value.dataRef.children = folders.map((obj) => {
return {
key: obj.name,
group: switchComponent.value.group,
title: obj.name,
path: obj.name,
children: [],
};
});
}
function handleSelectFolder(_, e) {
switch (e.node.dataRef.group) {
case 'private':
case 'public':
switchComponent.value = {
name: 'FileList',
group: e.node.dataRef.group,
path: e.node.dataRef.path,
dataRef: e.node.dataRef,
};
break;
case 'share':
switchComponent.value = {
name: 'ShareList',
group: e.node.dataRef.group,
path: e.node.dataRef.path,
dataRef: e.node.dataRef,
};
break;
}
}
function handleAppendFolder(folders: OssObject[]) {
switchComponent.value.dataRef.children = folders.map((obj) => {
return {
L,
switchComponent,
folderTree,
deleteEnabled,
expandedKeys,
fetchFolders,
handleSelectFolder,
handleAppendFolder,
key: obj.name,
group: switchComponent.value.group,
title: obj.name,
path: obj.name,
children: [],
};
},
});
});
}
</script>

1
apps/vue/src/views/account/center/FileList.vue

@ -155,6 +155,7 @@
path: record.path,
object: record.name,
}).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
deleteTableDataRecord(record.name);
props.selectGroup === 'private' && emit('delete:file:private', record);
props.selectGroup === 'public' && emit('delete:file:public', record);

100
apps/vue/src/views/account/center/index.vue

@ -1,18 +1,18 @@
<template>
<div :class="prefixCls">
<a-row :class="`${prefixCls}-top`">
<a-col :span="9" :class="`${prefixCls}-col`">
<a-row>
<a-col :span="8">
<Row :class="`${prefixCls}-top`">
<Col :span="9" :class="`${prefixCls}-col`">
<Row>
<Col :span="8">
<div :class="`${prefixCls}-top__avatar`">
<img width="70" :src="userInfo.avatar ?? headerImg" />
<span>{{ userInfo.realName ?? userInfo.username }}</span>
<div>{{ userInfo.description }}</div>
</div>
</a-col>
</a-row>
</a-col>
</a-row>
</Col>
</Row>
</Col>
</Row>
<div :class="`${prefixCls}-bottom`">
<Tabs
v-model:activeKey="activeTabKey"
@ -21,7 +21,7 @@
>
<template v-for="item in components" :key="item.key">
<TabPane :tab="item.name">
<component :is="item.component" />
<component :is="componentsRef[item.component]" />
</TabPane>
</template>
</Tabs>
@ -29,63 +29,47 @@
</div>
</template>
<script lang="ts">
import { Tag, Tabs, Row, Col } from 'ant-design-vue';
import { defineComponent, computed, ref } from 'vue';
import { CollapseContainer } from '/@/components/Container/index';
import Icon from '/@/components/Icon/index';
<script lang="ts" setup>
import { Tabs, Row, Col } from 'ant-design-vue';
import { computed, ref, shallowRef } from 'vue';
import headerImg from '/@/assets/images/header.jpg';
import { useUserStore } from '/@/store/modules/user';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useTabsStyle } from '/@/hooks/component/useStyles';
import Cloud from './Cloud.vue';
import Setting from './Setting.vue';
export default defineComponent({
components: {
Cloud,
CollapseContainer,
Icon,
Tag,
Tabs,
TabPane: Tabs.TabPane,
Setting,
[Row.name]: Row,
[Col.name]: Col,
const TabPane = Tabs.TabPane;
const componentsRef = shallowRef({
'Cloud': Cloud,
'Setting': Setting,
});
const prefixCls = 'account-center';
const userStore = useUserStore();
const activeTabKey = ref('Cloud');
const { L } = useLocalization(['AbpOssManagement', 'AbpSettingManagement']);
const components = [
{
key: 'Cloud',
name: L('MyCloud'),
component: 'Cloud',
},
setup() {
const userStore = useUserStore();
const activeTabKey = ref('cloud');
const { L } = useLocalization(['AbpOssManagement', 'AbpSettingManagement']);
const components = [
{
key: 'cloud',
name: L('MyCloud'),
component: 'cloud',
},
{
key: 'setting',
name: L('DisplayName:UserSetting'),
component: 'setting',
},
];
const tabsStyle = useTabsStyle(
'top',
{},
{
top: '80px',
}
);
const userInfo = computed(() => userStore.getUserInfo);
return {
activeTabKey,
tabsStyle,
prefixCls: 'account-center',
userInfo,
headerImg,
components,
};
{
key: 'Setting',
name: L('DisplayName:UserSetting'),
component: 'Setting',
},
});
];
const tabsStyle = useTabsStyle(
'top',
{},
{
top: '80px',
}
);
const userInfo = computed(() => userStore.getUserInfo);
</script>
<style lang="less" scoped>
.account-center {

37
apps/vue/src/views/account/setting/AccountBind.vue

@ -1,7 +1,7 @@
<template>
<CollapseContainer :title="L('Binding')" :canExpan="false">
<List>
<template v-for="item in list" :key="item.key">
<template v-for="item in getAccountBindList()" :key="item.key">
<ListItem>
<ListItemMeta>
<template #avatar>
@ -25,38 +25,25 @@
</List>
</CollapseContainer>
</template>
<script lang="ts">
<script lang="ts" setup>
import { List, Tag } from 'ant-design-vue';
import { defineComponent } from 'vue';
import { CollapseContainer } from '/@/components/Container/index';
import { useProfile } from './useProfile';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { MyProfile } from '/@/api/account/model/profilesModel';
import Icon from '/@/components/Icon/index';
export default defineComponent({
components: {
CollapseContainer,
List,
ListItem: List.Item,
ListItemMeta: List.Item.Meta,
Icon,
Tag,
},
props: {
profile: {
type: Object as PropType<MyProfile>,
}
},
setup(props) {
const { L } = useLocalization('AbpAccount');
const { getAccountBindList } = useProfile({ profile: props.profile });
return {
L,
list: getAccountBindList(),
};
},
const ListItem = List.Item;
const ListItemMeta = List.Item.Meta;
const props = defineProps({
profile: {
type: Object as PropType<MyProfile>,
}
});
const { L } = useLocalization('AbpAccount');
const { getAccountBindList } = useProfile({ profile: props.profile });
</script>
<style lang="less" scoped>
.avatar {

171
apps/vue/src/views/account/setting/BaseSetting.vue

@ -1,10 +1,10 @@
<template>
<CollapseContainer :title="L('BasicSettings')" :canExpan="false">
<a-row :gutter="24">
<a-col :span="14">
<Row :gutter="24">
<Col :span="14">
<BasicForm @register="register" />
</a-col>
<a-col :span="10">
</Col>
<Col :span="10">
<div class="change-avatar">
<div class="mb-2">{{ L('Avatar') }}</div>
<CropperAvatar
@ -16,8 +16,8 @@
@change="updateAvatar"
/>
</div>
</a-col>
</a-row>
</Col>
</Row>
<Button
type="primary"
:loading="confirmButton.loading"
@ -27,117 +27,96 @@
>
</CollapseContainer>
</template>
<script lang="ts">
<script lang="ts" setup>
import { Button, Row, Col } from 'ant-design-vue';
import { computed, defineComponent, reactive, watch } from 'vue';
import { computed, reactive, watch } from 'vue';
import { BasicForm, useForm } from '/@/components/Form/index';
import { CollapseContainer } from '/@/components/Container';
import { CropperAvatar } from '/@/components/Cropper';
import { useMessage } from '/@/hooks/web/useMessage';
import headerImg from '/@/assets/icons/64x64/color-user.png';
import { useUserStore } from '/@/store/modules/user';
import { upload } from '/@/api/oss-management/private';
import { changeAvatar } from '/@/api/account/claims';
import { update as updateProfile } from '/@/api/account/profiles';
import { MyProfile, UpdateMyProfile } from '/@/api/account/model/profilesModel';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useProfile } from './useProfile';
export default defineComponent({
components: {
BasicForm,
CollapseContainer,
Button,
ARow: Row,
ACol: Col,
CropperAvatar,
},
emits: ['profile-change'],
props: {
profile: {
type: Object as PropType<MyProfile>,
const emits = defineEmits(['profile-change']);
const props = defineProps({
profile: {
type: Object as PropType<MyProfile>,
}
});
const { getBaseSetschemas } = useProfile({ profile: props.profile });
const userStore = useUserStore();
const { createMessage } = useMessage();
const { L } = useLocalization('AbpAccount');
const [register, { getFieldsValue, setFieldsValue, validate }] = useForm({
labelWidth: 120,
schemas: getBaseSetschemas(),
showActionButtonGroup: false,
});
const confirmButton = reactive({
title: L('Submit'),
loading: false,
});
const avatar = computed(() => {
const { avatar } = userStore.getUserInfo;
return avatar ?? headerImg;
});
watch(
() => props.profile,
(profile) => {
if (profile) {
setFieldsValue(profile);
}
},
setup(props, { emit }) {
const { createMessage } = useMessage();
const { getBaseSetschemas } = useProfile({ profile: props.profile });
const userStore = useUserStore();
const { L } = useLocalization('AbpAccount');
const [register, { getFieldsValue, setFieldsValue, validate }] = useForm({
labelWidth: 120,
schemas: getBaseSetschemas(),
showActionButtonGroup: false,
});
const confirmButton = reactive({
title: L('Submit'),
loading: false,
});
const avatar = computed(() => {
const { avatar } = userStore.getUserInfo;
return avatar ?? headerImg;
});
watch(
() => props.profile,
(profile) => {
if (profile) {
setFieldsValue(profile);
}
},
{
immediate: true,
},
)
{
immediate: true,
},
)
function handleUploadAvatar(params: { file: Blob; name: string; filename: string }) {
return new Promise<void>((resolve, reject) => {
upload(params.file, 'avatar', params.filename)
.then((res) => {
const path = encodeURIComponent(res.data.path.substring(0, res.data.path.length - 1));
changeAvatar({ avatarUrl: `${path}/${res.data.name}` })
.then(() => {
emit('profile-change');
resolve({} as unknown as void);
})
.catch((err) => reject(err));
function handleUploadAvatar(params: { file: Blob; name: string; filename: string }) {
return new Promise<void>((resolve, reject) => {
upload(params.file, 'avatar', params.filename)
.then((res) => {
const path = encodeURIComponent(res.data.path.substring(0, res.data.path.length - 1));
changeAvatar({ avatarUrl: `${path}/${res.data.name}` })
.then(() => {
createMessage.success(L('Successful'));
emits('profile-change');
resolve({} as unknown as void);
})
.catch((err) => reject(err));
});
}
})
.catch((err) => reject(err));
});
}
function updateAvatar(src: string) {
const userinfo = userStore.getUserInfo;
userinfo.avatar = src;
userStore.setUserInfo(userinfo);
}
function updateAvatar(src: string) {
const userinfo = userStore.getUserInfo;
userinfo.avatar = src;
userStore.setUserInfo(userinfo);
}
function handleSubmit() {
validate().then(() => {
confirmButton.loading = true;
confirmButton.title = L('SavingWithThreeDot');
updateProfile(getFieldsValue() as UpdateMyProfile)
.then(() => {
createMessage.success(L('PersonalSettingsSaved'));
emit('profile-change');
})
.finally(() => {
confirmButton.loading = false;
confirmButton.title = L('Submit');
});
function handleSubmit() {
validate().then(() => {
confirmButton.loading = true;
confirmButton.title = L('SavingWithThreeDot');
updateProfile(getFieldsValue() as UpdateMyProfile)
.then(() => {
createMessage.success(L('PersonalSettingsSaved'));
emits('profile-change');
}).finally(() => {
confirmButton.loading = false;
confirmButton.title = L('Submit');
});
}
return {
L,
avatar,
register,
updateAvatar,
confirmButton,
handleUploadAvatar,
handleSubmit,
};
},
});
});
}
</script>
<style lang="less" scoped>

75
apps/vue/src/views/account/setting/MsgNotify.vue

@ -30,56 +30,47 @@
</template>
</Collapse>
</template>
<script lang="ts">
<script lang="ts" setup>
import { Card, List, Switch, Collapse } from 'ant-design-vue';
import { defineComponent, ref, onMounted } from 'vue';
import { ref, onMounted } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { ListItem, useProfile } from './useProfile';
import { ListItem as ProfileItem, useProfile } from './useProfile';
import { subscribe, unSubscribe } from '/@/api/messages/subscribes';
import { MyProfile } from '/@/api/account/model/profilesModel';
export default defineComponent({
components: {
Card,
Collapse,
CollapsePanel: Collapse.Panel,
List,
ListItem: List.Item,
ListItemMeta: List.Item.Meta,
Switch,
},
props: {
profile: {
type: Object as PropType<MyProfile>,
}
},
setup(props) {
const { L } = useLocalization('AbpAccount');
const notifyGroup = ref<{[key: string]: ListItem[]}>({});
const { getMsgNotifyList } = useProfile({ profile: props.profile });
function _fetchNotifies() {
getMsgNotifyList().then((res) => {
notifyGroup.value = res;
});
}
const CollapsePanel = Collapse.Panel;
const ListItem = List.Item;
const ListItemMeta = List.Item.Meta;
onMounted(_fetchNotifies);
const props = defineProps({
profile: {
type: Object as PropType<MyProfile>,
}
});
function handleChange(item: ListItem, checked) {
item.loading = true;
const api = checked ? subscribe(item.key) : unSubscribe(item.key);
api.finally(() => {
item.loading = false;
});
}
const { createMessage } = useMessage();
const { L } = useLocalization('AbpAccount');
const notifyGroup = ref<{[key: string]: ProfileItem[]}>({});
const { getMsgNotifyList } = useProfile({ profile: props.profile });
return {
L,
notifyGroup,
handleChange,
};
},
});
function _fetchNotifies() {
getMsgNotifyList().then((res) => {
notifyGroup.value = res;
});
}
onMounted(_fetchNotifies);
function handleChange(item: ProfileItem, checked) {
item.loading = true;
const api = checked ? subscribe(item.key) : unSubscribe(item.key);
api.then(() => {
createMessage.success(L('Successful'));
}).finally(() => {
item.loading = false;
});
}
</script>
<style lang="less" scoped>
.extra {

122
apps/vue/src/views/account/setting/SecureSetting.vue

@ -33,10 +33,10 @@
<SettingFormModal @register="registerModal" />
</div>
</template>
<script lang="ts">
import type { ListItem } from './useProfile';
<script lang="ts" setup>
import type { ListItem as ProfileItem } from './useProfile';
import { Button, List, Switch, Tag } from 'ant-design-vue';
import { defineComponent, ref, onMounted } from 'vue';
import { ref, onMounted } from 'vue';
import { CollapseContainer } from '/@/components/Container';
import { useModal } from '/@/components/Modal';
import { useProfile } from './useProfile';
@ -46,77 +46,59 @@
import { MyProfile } from '/@/api/account/model/profilesModel';
import SettingFormModal from './SettingFormModal.vue';
export default defineComponent({
components: {
Button,
CollapseContainer,
List,
ListItem: List.Item,
ListItemMeta: List.Item.Meta,
Switch,
Tag,
SettingFormModal,
},
props: {
profile: {
type: Object as PropType<MyProfile>,
}
},
setup(props) {
const { createMessage } = useMessage();
const { L } = useLocalization('AbpAccount');
const { getSecureSettingList } = useProfile({ profile: props.profile });
const secureSettingList = ref<ListItem[]>([]);
const [registerModal, { openModal }] = useModal();
const ListItem = List.Item;
const ListItemMeta = List.Item.Meta;
onMounted(() => {
getSecureSettingList().then((res) => {
secureSettingList.value = res;
});
});
function toggleCommand(item: ListItem) {
item.loading = true;
switch (item.key) {
case 'password':
case 'phoneNumber':
openModal(true, item);
item.loading = false;
break;
case 'email':
sendEmailConfirmLink({
email: item.description,
appName: 'STS',
returnUrl: window.location.href,
}).finally(() => {
item.loading = false;
});
break;
}
}
const props = defineProps({
profile: {
type: Object as PropType<MyProfile>,
}
});
function handleChange(item: ListItem, checked) {
item.loading = true;
switch (item.key) {
case 'twofactor':
changeTwoFactorEnabled(checked).then(() => {
createMessage.success(L('Successful'));
}).finally(() => {
item.loading = false;
});
break;
}
}
const { createMessage } = useMessage();
const { L } = useLocalization('AbpAccount');
const { getSecureSettingList } = useProfile({ profile: props.profile });
const secureSettingList = ref<ProfileItem[]>([]);
const [registerModal, { openModal }] = useModal();
return {
L,
secureSettingList,
handleChange,
toggleCommand,
registerModal,
};
},
onMounted(() => {
getSecureSettingList().then((res) => {
secureSettingList.value = res;
});
});
function toggleCommand(item: ProfileItem) {
item.loading = true;
switch (item.key) {
case 'password':
case 'phoneNumber':
openModal(true, item);
item.loading = false;
break;
case 'email':
sendEmailConfirmLink({
email: item.description,
appName: 'STS',
returnUrl: window.location.href,
}).finally(() => {
item.loading = false;
});
break;
}
}
function handleChange(item: ProfileItem, checked) {
item.loading = true;
switch (item.key) {
case 'twofactor':
changeTwoFactorEnabled(checked).then(() => {
createMessage.success(L('Successful'));
}).finally(() => {
item.loading = false;
});
break;
}
}
</script>
<style lang="less" scoped>
.extra {

63
apps/vue/src/views/account/setting/index.vue

@ -1,10 +1,10 @@
<template>
<ScrollContainer>
<div ref="wrapperRef" :class="prefixCls">
<Tabs tab-position="left" :tabBarStyle="tabBarStyle">
<div ref="wrapperRef" class="account-setting">
<Tabs tab-position="left" :tabBarStyle="{ width: '220px' }">
<template v-for="item in getSettingList()" :key="item.key">
<TabPane :tab="item.name">
<component :is="item.component" :profile="profileRef" @profile-change="initUserInfo" />
<component :is="componentsRef[item.component]" :profile="profileRef" @profile-change="initUserInfo" />
</TabPane>
</template>
</Tabs>
@ -12,8 +12,8 @@
</ScrollContainer>
</template>
<script lang="ts">
import { defineComponent, ref, onMounted } from 'vue';
<script lang="ts" setup>
import { ref, shallowRef, onMounted } from 'vue';
import { Tabs } from 'ant-design-vue';
import { ScrollContainer } from '/@/components/Container/index';
import { getSettingList } from './data';
@ -24,42 +24,29 @@
import SecureSetting from './SecureSetting.vue';
import AccountBind from './AccountBind.vue';
import MsgNotify from './MsgNotify.vue';
export default defineComponent({
components: {
ScrollContainer,
Tabs,
TabPane: Tabs.TabPane,
BaseSetting,
SecureSetting,
AccountBind,
MsgNotify,
},
setup() {
const profileRef = ref<MyProfile>();
onMounted(fetchProfile);
async function fetchProfile() {
const profile = await getProfile();
profileRef.value = profile;
}
const TabPane = Tabs.TabPane;
async function initUserInfo() {
const abpStore = useAbpStoreWithOut();
await abpStore.initlizeAbpApplication();
await fetchProfile();
}
return {
prefixCls: 'account-setting',
profileRef,
initUserInfo,
getSettingList,
tabBarStyle: {
width: '220px',
},
};
},
const componentsRef = shallowRef({
'BaseSetting': BaseSetting,
'SecureSetting': SecureSetting,
'AccountBind': AccountBind,
'MsgNotify': MsgNotify,
});
const profileRef = ref<MyProfile>();
onMounted(fetchProfile);
async function fetchProfile() {
const profile = await getProfile();
profileRef.value = profile;
}
async function initUserInfo() {
const abpStore = useAbpStoreWithOut();
await abpStore.initlizeAbpApplication();
await fetchProfile();
}
</script>
<style lang="less">
.account-setting {

164
apps/vue/src/views/auditing/components/AuditLogModal.vue

@ -1,6 +1,7 @@
<template>
<BasicModal @register="registerModal" :width="800" :height="400" :title="L('AuditLog')">
<Form
ref="formElRef"
:colon="false"
:labelCol="{ span: 6 }"
:wrapperCol="{ span: 18 }"
@ -145,8 +146,8 @@
</BasicModal>
</template>
<script lang="ts">
import { computed, defineComponent, ref, watch, unref } from 'vue';
<script lang="ts" setup>
import { computed, nextTick, ref, unref } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useTabsStyle } from '/@/hooks/component/useStyles';
import { Collapse, Form, Tabs, Tag } from 'ant-design-vue';
@ -158,101 +159,74 @@
import { AuditLog } from '/@/api/auditing/model/auditLogModel';
import { formatToDateTime } from '/@/utils/dateUtil';
import { tryToJson } from '/@/utils/strings';
export default defineComponent({
name: 'AuditLogModal',
components: {
BasicModal,
BasicTable,
CodeEditor,
Collapse,
CollapsePanel: Collapse.Panel,
Form,
FormItem: Form.Item,
Tag,
Tabs,
TabPane: Tabs.TabPane,
},
setup() {
const { L } = useLocalization('AbpAuditLogging');
const activeKey = ref('basic');
const auditLogIdRef = ref('');
const tabsStyle = useTabsStyle();
const modelRef = ref<AuditLog>({} as AuditLog);
const [registerModal] = useModalInner((model) => {
auditLogIdRef.value = model.id;
activeKey.value = 'basic';
});
const columns: BasicColumn[] = [
{
title: 'id',
dataIndex: 'id',
width: 1,
ifShow: false,
},
{
title: L('PropertyName'),
dataIndex: 'propertyName',
align: 'left',
width: 120,
sorter: true,
},
{
title: L('NewValue'),
dataIndex: 'newValue',
align: 'left',
width: 200,
sorter: true,
},
{
title: L('OriginalValue'),
dataIndex: 'originalValue',
align: 'left',
width: 200,
sorter: true,
},
{
title: L('PropertyTypeFullName'),
dataIndex: 'propertyTypeFullName',
align: 'left',
width: 300,
sorter: true,
},
];
const { entityChangeTypeColor, entityChangeType, httpMethodColor, httpStatusCodeColor } =
useAuditLog();
const formatJsonVal = computed(() => {
return (jsonString: string) => tryToJson(jsonString);
});
const formatDateVal = computed(() => {
return (dateVal) => formatToDateTime(dateVal, 'YYYY-MM-DD HH:mm:ss');
});
watch(
() => unref(auditLogIdRef),
(id) => {
if (id) {
getById(id).then((res) => {
modelRef.value = res;
});
}
},
);
const CollapsePanel = Collapse.Panel;
const FormItem = Form.Item;
const TabPane = Tabs.TabPane;
return {
L,
MODE,
columns,
modelRef,
activeKey,
tabsStyle,
entityChangeType,
entityChangeTypeColor,
httpMethodColor,
httpStatusCodeColor,
registerModal,
formatJsonVal,
formatDateVal,
};
const { L } = useLocalization('AbpAuditLogging');
const formElRef = ref<any>();
const activeKey = ref('basic');
const tabsStyle = useTabsStyle();
const modelRef = ref<AuditLog>({} as AuditLog);
const [registerModal] = useModalInner((model) => {
activeKey.value = 'basic';
nextTick(() => {
fetchAuditLog(model.id);
});
});
const columns: BasicColumn[] = [
{
title: 'id',
dataIndex: 'id',
width: 1,
ifShow: false,
},
{
title: L('PropertyName'),
dataIndex: 'propertyName',
align: 'left',
width: 120,
sorter: true,
},
{
title: L('NewValue'),
dataIndex: 'newValue',
align: 'left',
width: 200,
sorter: true,
},
{
title: L('OriginalValue'),
dataIndex: 'originalValue',
align: 'left',
width: 200,
sorter: true,
},
{
title: L('PropertyTypeFullName'),
dataIndex: 'propertyTypeFullName',
align: 'left',
width: 300,
sorter: true,
},
];
const { entityChangeTypeColor, entityChangeType, httpMethodColor, httpStatusCodeColor } =
useAuditLog();
const formatJsonVal = computed(() => {
return (jsonString: string) => tryToJson(jsonString);
});
const formatDateVal = computed(() => {
return (dateVal) => formatToDateTime(dateVal, 'YYYY-MM-DD HH:mm:ss');
});
function fetchAuditLog(id?: string) {
const formEl = unref(formElRef);
formEl?.resetFields();
if (id) {
getById(id).then((res) => {
modelRef.value = res;
});
}
}
</script>

105
apps/vue/src/views/auditing/components/AuditLogTable.vue

@ -35,75 +35,62 @@
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { Modal, Tag } from 'ant-design-vue';
<script lang="ts" setup>
import { Tag } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicTable, TableAction, useTable } from '/@/components/Table';
import { getDataColumns } from './TableData';
import { getSearchFormSchemas } from './ModalData';
import { useModal } from '/@/components/Modal';
import AuditLogModal from './AuditLogModal.vue';
import { useAuditLog } from '../hooks/useAuditLog';
import { useMessage } from '/@/hooks/web/useMessage';
import { deleteById, getList } from '/@/api/auditing/auditLog';
import { formatPagedRequest } from '/@/utils/http/abp/helper';
import AuditLogModal from './AuditLogModal.vue';
export default defineComponent({
name: 'AuditLogTable',
components: { AuditLogModal, BasicTable, Tag, TableAction },
setup() {
const { L } = useLocalization('AbpAuditLogging');
const [registerTable, { reload }] = useTable({
rowKey: 'id',
title: L('AuditLog'),
columns: getDataColumns(),
api: getList,
beforeFetch: formatPagedRequest,
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: false,
immediate: true,
formConfig: getSearchFormSchemas(),
scroll: { x: 'max-content', y: '100%' },
actionColumn: {
width: 180,
title: L('Actions'),
dataIndex: 'action',
},
});
const [registerModal, { openModal }] = useModal();
const { httpMethodColor, httpStatusCodeColor } = useAuditLog();
const { createMessage, createConfirm } = useMessage();
const { L } = useLocalization('AbpAuditLogging');
const [registerTable, { reload }] = useTable({
rowKey: 'id',
title: L('AuditLog'),
columns: getDataColumns(),
api: getList,
beforeFetch: formatPagedRequest,
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: false,
immediate: true,
formConfig: getSearchFormSchemas(),
scroll: { x: 'max-content', y: '100%' },
actionColumn: {
width: 180,
title: L('Actions'),
dataIndex: 'action',
},
});
const [registerModal, { openModal }] = useModal();
const { httpMethodColor, httpStatusCodeColor } = useAuditLog();
function handleShow(record) {
openModal(true, record, true);
}
function handleShow(record) {
openModal(true, record, true);
}
function handleDelete(record) {
Modal.warning({
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
reload();
});
},
function handleDelete(record) {
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reload();
});
}
return {
L,
httpMethodColor,
httpStatusCodeColor,
registerTable,
registerModal,
handleShow,
handleDelete,
};
},
});
},
});
}
</script>

2
apps/vue/src/views/caching-management/cache/datas/ModalData.ts

@ -69,7 +69,7 @@ export function getModalFormSchemas(): FormSchema[] {
label: L('DisplayName:Values'),
colProps: { span: 24 },
render: ({ values }) => {
return createVNode(JsonPreview, {
return createVNode(JsonPreview!, {
data: values.values,
});
},

78
apps/vue/src/views/feature/src/FeatureModal.vue

@ -31,7 +31,7 @@
style="width: 100%"
v-model:value="feature.value"
/>
<Input v-else v-model:value="feature.value" />
<BInput v-else v-model:value="feature.value" />
</div>
<Select
v-else-if="feature.valueType.name === 'SelectionStringValueType'"
@ -52,60 +52,38 @@
</BasicModal>
</template>
<script lang="ts">
import { computed, defineComponent, ref } from 'vue';
<script lang="ts" setup>
import { computed, ref } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { Checkbox, Form, InputNumber, Select, Tabs } from 'ant-design-vue';
import { Input } from '/@/components/Input';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { useFeature } from '../hooks/useFeature';
export default defineComponent({
components: {
BasicModal,
Checkbox,
Form,
FormItem: Form.Item,
Input,
InputNumber,
Select,
Option: Select.Option,
Tabs,
TabPane: Tabs.TabPane,
},
setup() {
const { L } = useLocalization('AbpFeatureManagement');
// TODO: ?
const localizer = computed(() => {
return (resourceName: string, key: string) => {
const { L: RL } = useLocalization(resourceName);
return RL(key);
};
});
const formRel = ref(null);
const providerName = ref('');
const providerKey = ref(null);
const [registerModal, modalMethods] = useModalInner((data) => {
providerName.value = data.providerName;
providerKey.value = data.providerKey;
});
const { featureGroup, featureGroupKey, validator, handleSubmit, onGroupChange } = useFeature({
providerName,
providerKey,
formRel,
modalMethods,
});
return {
L,
localizer,
formRel,
registerModal,
featureGroup,
featureGroupKey,
validator,
handleSubmit,
onGroupChange,
};
},
const FormItem = Form.Item;
const Option = Select.Option;
const TabPane = Tabs.TabPane;
const BInput = Input!;
const { L } = useLocalization('AbpFeatureManagement');
// TODO: ?
const localizer = computed(() => {
return (resourceName: string, key: string) => {
const { L: RL } = useLocalization(resourceName);
return RL(key);
};
});
const formRel = ref(null);
const providerName = ref('');
const providerKey = ref(null);
const [registerModal, modalMethods] = useModalInner((data) => {
providerName.value = data.providerName;
providerKey.value = data.providerKey;
});
const { featureGroup, featureGroupKey, validator, handleSubmit, onGroupChange } = useFeature({
providerName,
providerKey,
formRel,
modalMethods,
});
</script>

159
apps/vue/src/views/identity-server/api-resources/components/ApiResourceModal.vue

@ -13,8 +13,8 @@
ref="formElRef"
:model="resourceRef"
:rules="formRules"
:label-col="labelCol"
:wrapper-col="wrapperCol"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 18 }"
>
<Tabs v-model:activeKey="tabActivedKey" @change="handleChangeTab">
<!-- Api 资源基本信息 -->
@ -28,19 +28,19 @@
}}</Checkbox>
</FormItem>
<FormItem name="name" required :label="L('Name')">
<Input v-model:value="resourceRef.name" :disabled="isEdit" />
<BInput v-model:value="resourceRef.name" :disabled="isEdit" />
</FormItem>
<FormItem name="displayName" :label="L('DisplayName')">
<Input v-model:value="resourceRef.displayName" />
<BInput v-model:value="resourceRef.displayName" />
</FormItem>
<FormItem name="description" :label="L('Description')">
<Input v-model:value="resourceRef.description" />
<BInput v-model:value="resourceRef.description" />
</FormItem>
<FormItem
name="allowedAccessTokenSigningAlgorithms"
:label="L('AllowedAccessTokenSigningAlgorithms')"
>
<Input v-model:value="resourceRef.allowedAccessTokenSigningAlgorithms" />
<BInput v-model:value="resourceRef.allowedAccessTokenSigningAlgorithms" />
</FormItem>
</TabPane>
@ -64,14 +64,14 @@
</span>
<template #overlay>
<Menu @click="handleClickMenu">
<MenuItem key="api-resource-secret">{{ L('Secret') }}</MenuItem>
<MenuItem key="properties">{{ L('Propertites') }}</MenuItem>
<MenuItem key="ApiResourceSecret">{{ L('Secret') }}</MenuItem>
<MenuItem key="Properties">{{ L('Propertites') }}</MenuItem>
</Menu>
</template>
</Dropdown>
</template>
<component
:is="advancedComponent"
:is="componentsRef[advancedComponent]"
:secrets="resourceRef.secrets"
:properties="resourceRef.properties"
@secrets-new="handleNewSecret"
@ -85,8 +85,9 @@
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
<script lang="ts" setup>
import { ref, shallowRef } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { DownOutlined } from '@ant-design/icons-vue';
import { Checkbox, Dropdown, Menu, Tabs, Form } from 'ant-design-vue';
@ -101,94 +102,58 @@
import ApiResourceSecret from './ApiResourceSecret.vue';
import UserClaim from '../../components/UserClaim.vue';
import Properties from '../../components/Properties.vue';
export default defineComponent({
name: 'ApiResourceModal',
components: {
UserClaim,
Properties,
ApiResourceScope,
ApiResourceSecret,
BasicModal,
DownOutlined,
Form,
FormItem: Form.Item,
Dropdown,
Menu,
MenuItem: Menu.Item,
Tabs,
TabPane: Tabs.TabPane,
Input,
Checkbox,
},
emits: ['change', 'register'],
setup(_, { emit }) {
const { L } = useLocalization('AbpIdentityServer');
const formElRef = ref<any>(null);
const resourceIdRef = ref('');
const tabActivedKey = ref('basic');
const advancedComponent = ref('api-resource-secret');
const [registerModal, { changeOkLoading }] = useModalInner((val) => {
resourceIdRef.value = val.id;
});
const {
isEdit,
resourceRef,
formRules,
formTitle,
handleChangeTab,
handleVisibleModal,
handleSubmit,
} = useModal({
resourceIdRef,
formElRef,
tabActivedKey,
});
const { handleNewSecret, handleDeleteSecret } = useSecret({ resourceRef });
const { handleNewProperty, handleDeleteProperty } = useProperty({ resourceRef });
const { targetClaims, handleClaimChange } = useClaim({ resourceRef });
const { targetScopes, handleScopeChange } = useScope({ resourceRef });
function handleClickMenu(e) {
tabActivedKey.value = 'advanced';
advancedComponent.value = e.key;
}
const FormItem = Form.Item;
const MenuItem = Menu.Item;
const TabPane = Tabs.TabPane;
const BInput = Input!;
function handleOk() {
changeOkLoading(true);
handleSubmit()
.then(() => {
emit('change');
})
.finally(() => {
changeOkLoading(false);
});
}
const componentsRef = shallowRef({
'ApiResourceSecret': ApiResourceSecret,
'Properties': Properties,
});
const emits = defineEmits(['change', 'register']);
return {
L,
isEdit,
formElRef,
formRules,
formTitle,
tabActivedKey,
registerModal,
resourceRef,
advancedComponent,
labelCol: { span: 6 },
wrapperCol: { span: 18 },
handleClickMenu,
handleNewSecret,
handleDeleteSecret,
handleNewProperty,
handleDeleteProperty,
handleChangeTab,
handleVisibleModal,
handleOk,
targetScopes,
handleScopeChange,
targetClaims,
handleClaimChange,
};
},
const { createMessage } = useMessage();
const { L } = useLocalization('AbpIdentityServer');
const formElRef = ref<any>(null);
const resourceIdRef = ref('');
const tabActivedKey = ref('basic');
const advancedComponent = ref('ApiResourceSecret');
const [registerModal, { changeOkLoading }] = useModalInner((val) => {
resourceIdRef.value = val.id;
});
const {
isEdit,
resourceRef,
formRules,
formTitle,
handleChangeTab,
handleVisibleModal,
handleSubmit,
} = useModal({
resourceIdRef,
formElRef,
tabActivedKey,
});
const { handleNewSecret, handleDeleteSecret } = useSecret({ resourceRef });
const { handleNewProperty, handleDeleteProperty } = useProperty({ resourceRef });
const { targetClaims, handleClaimChange } = useClaim({ resourceRef });
const { targetScopes, handleScopeChange } = useScope({ resourceRef });
function handleClickMenu(e) {
tabActivedKey.value = 'advanced';
advancedComponent.value = e.key;
}
function handleOk() {
changeOkLoading(true);
handleSubmit().then(() => {
createMessage.success(L('Successful'));
emits('change');
}).finally(() => {
changeOkLoading(false);
});
}
</script>

65
apps/vue/src/views/identity-server/api-resources/components/ApiResourceScope.vue

@ -12,48 +12,41 @@
/>
</template>
<script lang="ts">
import { defineComponent, onMounted, ref } from 'vue';
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { Transfer } from 'ant-design-vue';
import { discovery } from '/@/api/identity-server/identityServer';
export default defineComponent({
name: 'ApiResourceScope',
components: { Transfer },
props: {
targetScopes: { type: Object as PropType<string[]>, required: true },
},
emits: ['change'],
setup(_, { emit }) {
const { L } = useLocalization('AbpIdentityServer');
const supportedScopes = ref<
{
key: string;
title: string;
}[]
>([]);
const emits = defineEmits(['change']);
onMounted(() => {
discovery().then((res) => {
supportedScopes.value = res.scopes_supported.map((scope) => {
return {
key: scope,
title: scope,
};
});
});
});
defineProps({
targetScopes: {
type: Object as PropType<string[]>,
required: true,
},
});
function handleChange(targetKeys, direction, moveKeys) {
emit('change', targetKeys, direction, moveKeys);
}
const { L } = useLocalization('AbpIdentityServer');
const supportedScopes = ref<
{
key: string;
title: string;
}[]
>([]);
return {
L,
supportedScopes,
handleChange,
};
},
onMounted(() => {
discovery().then((res) => {
supportedScopes.value = res.scopes_supported.map((scope) => {
return {
key: scope,
title: scope,
};
});
});
});
function handleChange(targetKeys, direction, moveKeys) {
emits('change', targetKeys, direction, moveKeys);
}
</script>

89
apps/vue/src/views/identity-server/api-resources/components/ApiResourceSecret.vue

@ -2,7 +2,7 @@
<div>
<BasicTable
rowKey="type"
:columns="columns"
:columns="getSecretColumns()"
:dataSource="secrets"
:pagination="false"
:showTableSetting="true"
@ -38,8 +38,9 @@
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
<script lang="ts" setup>
import { ref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { Button } from 'ant-design-vue';
import { BasicForm, useForm } from '/@/components/Form';
@ -49,60 +50,40 @@
import { getSecretColumns } from '../datas/TableData';
import { getSecretFormSchemas } from '../datas/ModalData';
export default defineComponent({
name: 'ApiResourceSecret',
components: {
BasicForm,
BasicModal,
BasicTable,
Button,
TableAction,
const emits = defineEmits(['register', 'secrets-new', 'secrets-delete']);
defineProps({
secrets: {
type: [Array] as PropType<ApiResourceSecret[]>,
required: true,
default: () => [],
},
props: {
secrets: {
type: [Array] as PropType<ApiResourceSecret[]>,
required: true,
default: () => [],
},
},
emits: ['register', 'secrets-new', 'secrets-delete'],
setup(_, { emit }) {
const { L } = useLocalization('AbpIdentityServer');
const title = ref('');
const [registerForm, { validate, resetFields }] = useForm({
labelWidth: 120,
showActionButtonGroup: false,
schemas: getSecretFormSchemas(),
});
const [registerModal, { openModal, closeModal }] = useModal();
});
function handleAddNew() {
title.value = L('Secret:New');
openModal(true);
}
const { createMessage } = useMessage();
const { L } = useLocalization('AbpIdentityServer');
const title = ref('');
const [registerForm, { validate, resetFields }] = useForm({
labelWidth: 120,
showActionButtonGroup: false,
schemas: getSecretFormSchemas(),
});
const [registerModal, { openModal, closeModal }] = useModal();
function handleDelete(record) {
emit('secrets-delete', record);
}
function handleAddNew() {
title.value = L('Secret:New');
openModal(true);
}
function handleSubmit() {
validate().then((input) => {
emit('secrets-new', input);
resetFields();
closeModal();
});
}
function handleDelete(record) {
emits('secrets-delete', record);
}
return {
L,
title,
handleAddNew,
handleDelete,
handleSubmit,
columns: getSecretColumns(),
registerForm,
registerModal,
};
},
});
function handleSubmit() {
validate().then((input) => {
createMessage.success(L('Successful'));
emits('secrets-new', input);
resetFields();
closeModal();
});
}
</script>

122
apps/vue/src/views/identity-server/api-resources/components/ApiResourceTable.vue

@ -6,10 +6,12 @@
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'enabled'">
<Switch :checked="record.enabled" readonly />
<CheckOutlined v-if="record.enabled" class="enable" />
<CloseOutlined v-else class="disable" />
</template>
<template v-if="column.key === 'showInDiscoveryDocument'">
<Switch :checked="record.showInDiscoveryDocument" readonly />
<CheckOutlined v-if="record.showInDiscoveryDocument" class="enable" />
<CloseOutlined v-else class="disable" />
</template>
<template v-else-if="column.key === 'action'">
<TableAction
@ -36,9 +38,10 @@
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { Button, Modal, Switch } from 'ant-design-vue';
<script lang="ts" setup>
import { Button } from 'ant-design-vue';
import { CheckOutlined, CloseOutlined } from '@ant-design/icons-vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicTable, TableAction, useTable } from '/@/components/Table';
import { useModal } from '/@/components/Modal';
@ -48,70 +51,57 @@
import { formatPagedRequest } from '/@/utils/http/abp/helper';
import ApiResourceModal from './ApiResourceModal.vue';
export default defineComponent({
name: 'ApiResourceTable',
components: { ApiResourceModal, BasicTable, Button, Switch, TableAction },
setup() {
const { L } = useLocalization('AbpIdentityServer');
const [registerModal, { openModal, closeModal }] = useModal();
const [registerTable, { reload }] = useTable({
rowKey: 'id',
title: L('DisplayName:ApiResources'),
columns: getDataColumns(),
api: getList,
beforeFetch: formatPagedRequest,
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: true,
immediate: true,
canColDrag: true,
formConfig: getSearchFormSchemas(),
actionColumn: {
width: 200,
title: L('Actions'),
dataIndex: 'action',
},
});
const { createMessage, createConfirm } = useMessage();
const { L } = useLocalization('AbpIdentityServer');
const [registerModal, { openModal, closeModal }] = useModal();
const [registerTable, { reload }] = useTable({
rowKey: 'id',
title: L('DisplayName:ApiResources'),
columns: getDataColumns(),
api: getList,
beforeFetch: formatPagedRequest,
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: true,
immediate: true,
canColDrag: true,
formConfig: getSearchFormSchemas(),
actionColumn: {
width: 200,
title: L('Actions'),
dataIndex: 'action',
},
});
function handleAddNew() {
openModal(true, {});
}
function handleAddNew() {
openModal(true, {});
}
function handleEdit(record) {
openModal(true, record);
}
function handleEdit(record) {
openModal(true, record);
}
function handleChange() {
closeModal();
reload();
}
function handleChange() {
closeModal();
reload();
}
function handleDelete(record) {
Modal.warning({
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
reload();
});
},
function handleDelete(record) {
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reload();
});
}
return {
L,
registerModal,
registerTable,
handleAddNew,
handleDelete,
handleEdit,
handleChange,
};
},
});
},
});
}
</script>

4
apps/vue/src/views/identity-server/api-resources/datas/TableData.ts

@ -36,14 +36,14 @@ export function getDataColumns(): BasicColumn[] {
{
title: L('Resource:Enabled'),
dataIndex: 'enabled',
align: 'left',
align: 'center',
width: 200,
sorter: true,
},
{
title: L('ShowInDiscoveryDocument'),
dataIndex: 'showInDiscoveryDocument',
align: 'left',
align: 'center',
width: 200,
sorter: true,
},

17
apps/vue/src/views/identity-server/api-resources/hooks/useModal.ts

@ -1,8 +1,8 @@
import type { Ref } from 'vue';
import { computed, ref, reactive, unref, watch } from 'vue';
import { message } from 'ant-design-vue';
import { cloneDeep } from 'lodash-es';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useValidation } from '/@/hooks/abp/useValidation';
@ -16,6 +16,7 @@ interface UseModal {
}
export function useModal({ resourceIdRef, formElRef, tabActivedKey }: UseModal) {
const { createMessage } = useMessage();
const { L } = useLocalization('AbpIdentityServer');
const { ruleCreator } = useValidation();
const resourceRef = ref<ApiResource>({} as ApiResource);
@ -80,14 +81,12 @@ export function useModal({ resourceIdRef, formElRef, tabActivedKey }: UseModal)
const api = isEdit.value
? update(input.id, Object.assign(input))
: create(Object.assign(input));
api
.then((res) => {
message.success(L('Successful'));
resolve(res);
})
.catch((error) => {
reject(error);
});
api.then((res) => {
createMessage.success(L('Successful'));
resolve(res);
}).catch((error) => {
reject(error);
});
})
.catch((error) => {
reject(error);

135
apps/vue/src/views/identity-server/api-scopes/components/ApiScopeModal.vue

@ -13,8 +13,8 @@
ref="formElRef"
:model="modelRef"
:rules="formRules"
:label-col="labelCol"
:wrapper-col="wrapperCol"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 18 }"
>
<Tabs v-model:activeKey="tabActivedKey" @change="handleChangeTab">
<!-- Api 资源基本信息 -->
@ -65,7 +65,7 @@
</Dropdown>
</template>
<component
:is="advancedComponent"
:is="componentsRef[advancedComponent]"
:properties="modelRef.properties"
@props-new="handleNewProperty"
@props-delete="handleDeleteProperty"
@ -76,8 +76,9 @@
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
<script lang="ts" setup>
import { ref, shallowRef } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { DownOutlined } from '@ant-design/icons-vue';
import { Checkbox, Dropdown, Menu, Tabs, Form } from 'ant-design-vue';
@ -88,86 +89,54 @@
import { useProperty } from '../hooks/useProperty';
import UserClaim from '../../components/UserClaim.vue';
import Properties from '../../components/Properties.vue';
export default defineComponent({
name: 'ApiScopeModal',
components: {
UserClaim,
Properties,
BasicModal,
DownOutlined,
Form,
FormItem: Form.Item,
Dropdown,
Menu,
MenuItem: Menu.Item,
Tabs,
TabPane: Tabs.TabPane,
Input,
Checkbox,
},
emits: ['change', 'register'],
setup(_, { emit }) {
const { L } = useLocalization('AbpIdentityServer');
const formElRef = ref<any>(null);
const modelIdRef = ref('');
const tabActivedKey = ref('basic');
const advancedComponent = ref('properties');
const [registerModal, { changeOkLoading }] = useModalInner((val) => {
modelIdRef.value = val.id;
});
const {
isEdit,
modelRef,
formRules,
formTitle,
handleChangeTab,
handleVisibleModal,
handleSubmit,
} = useModal({
modelIdRef,
formElRef,
tabActivedKey,
});
const { handleNewProperty, handleDeleteProperty } = useProperty({ modelRef });
const { targetClaims, handleClaimChange } = useClaim({ modelRef });
function handleClickMenu(e) {
tabActivedKey.value = 'advanced';
advancedComponent.value = e.key;
}
const FormItem = Form.Item;
const MenuItem = Menu.Item;
const TabPane = Tabs.TabPane;
function handleOk() {
changeOkLoading(true);
handleSubmit()
.then(() => {
emit('change');
})
.finally(() => {
changeOkLoading(false);
});
}
const componentsRef = shallowRef({
'properties': Properties,
});
const emits = defineEmits(['change', 'register']);
return {
L,
isEdit,
formElRef,
formRules,
formTitle,
tabActivedKey,
registerModal,
modelRef,
advancedComponent,
labelCol: { span: 6 },
wrapperCol: { span: 18 },
handleClickMenu,
handleNewProperty,
handleDeleteProperty,
handleChangeTab,
handleVisibleModal,
handleOk,
targetClaims,
handleClaimChange,
};
},
const { createMessage } = useMessage();
const { L } = useLocalization('AbpIdentityServer');
const formElRef = ref<any>(null);
const modelIdRef = ref('');
const tabActivedKey = ref('basic');
const advancedComponent = ref('properties');
const [registerModal, { changeOkLoading }] = useModalInner((val) => {
modelIdRef.value = val.id;
});
const {
isEdit,
modelRef,
formRules,
formTitle,
handleChangeTab,
handleVisibleModal,
handleSubmit,
} = useModal({
modelIdRef,
formElRef,
tabActivedKey,
});
const { handleNewProperty, handleDeleteProperty } = useProperty({ modelRef });
const { targetClaims, handleClaimChange } = useClaim({ modelRef });
function handleClickMenu(e) {
tabActivedKey.value = 'advanced';
advancedComponent.value = e.key;
}
function handleOk() {
changeOkLoading(true);
handleSubmit() .then(() => {
createMessage.success(L('Successful'));
emits('change');
}) .finally(() => {
changeOkLoading(false);
});
}
</script>

128
apps/vue/src/views/identity-server/api-scopes/components/ApiScopeTable.vue

@ -6,16 +6,20 @@
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'required'">
<Switch :checked="record.required" readonly />
<CheckOutlined v-if="record.required" class="enable" />
<CloseOutlined v-else class="disable" />
</template>
<template v-else-if="column.key === 'enabled'">
<Switch :checked="record.enabled" readonly />
<CheckOutlined v-if="record.enabled" class="enable" />
<CloseOutlined v-else class="disable" />
</template>
<template v-else-if="column.key === 'emphasize'">
<Switch :checked="record.emphasize" readonly />
<CheckOutlined v-if="record.emphasize" class="enable" />
<CloseOutlined v-else class="disable" />
</template>
<template v-else-if="column.key === 'showInDiscoveryDocument'">
<Switch :checked="record.showInDiscoveryDocument" readonly />
<CheckOutlined v-if="record.showInDiscoveryDocument" class="enable" />
<CloseOutlined v-else class="disable" />
</template>
<template v-else-if="column.key === 'action'">
<TableAction
@ -42,9 +46,10 @@
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { Button, Modal, Switch } from 'ant-design-vue';
<script lang="ts" setup>
import { Button } from 'ant-design-vue';
import { CheckOutlined, CloseOutlined } from '@ant-design/icons-vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicTable, TableAction, useTable } from '/@/components/Table';
import { useModal } from '/@/components/Modal';
@ -54,70 +59,57 @@
import { formatPagedRequest } from '/@/utils/http/abp/helper';
import ApiScopeModal from './ApiScopeModal.vue';
export default defineComponent({
name: 'ApiScopeTable',
components: { ApiScopeModal, BasicTable, Button, Switch, TableAction },
setup() {
const { L } = useLocalization('AbpIdentityServer');
const [registerModal, { openModal, closeModal }] = useModal();
const [registerTable, { reload }] = useTable({
rowKey: 'id',
title: L('DisplayName:ApiScopes'),
columns: getDataColumns(),
api: getList,
beforeFetch: formatPagedRequest,
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: true,
immediate: true,
canColDrag: true,
formConfig: getSearchFormSchemas(),
actionColumn: {
width: 200,
title: L('Actions'),
dataIndex: 'action',
},
});
const { createMessage, createConfirm } = useMessage();
const { L } = useLocalization('AbpIdentityServer');
const [registerModal, { openModal, closeModal }] = useModal();
const [registerTable, { reload }] = useTable({
rowKey: 'id',
title: L('DisplayName:ApiScopes'),
columns: getDataColumns(),
api: getList,
beforeFetch: formatPagedRequest,
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: true,
immediate: true,
canColDrag: true,
formConfig: getSearchFormSchemas(),
actionColumn: {
width: 200,
title: L('Actions'),
dataIndex: 'action',
},
});
function handleAddNew() {
openModal(true, {});
}
function handleAddNew() {
openModal(true, {});
}
function handleEdit(record) {
openModal(true, record);
}
function handleEdit(record) {
openModal(true, record);
}
function handleChange() {
closeModal();
reload();
}
function handleChange() {
closeModal();
reload();
}
function handleDelete(record) {
Modal.warning({
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
reload();
});
},
function handleDelete(record) {
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reload();
});
}
return {
L,
registerModal,
registerTable,
handleAddNew,
handleDelete,
handleEdit,
handleChange,
};
},
});
},
});
}
</script>

32
apps/vue/src/views/identity-server/api-scopes/datas/TableData.ts

@ -11,6 +11,20 @@ export function getDataColumns(): BasicColumn[] {
width: 1,
ifShow: false,
},
{
title: L('Enabled'),
dataIndex: 'enabled',
align: 'center',
width: 150,
sorter: true,
},
{
title: L('Required'),
dataIndex: 'required',
align: 'center',
width: 150,
sorter: true,
},
{
title: L('Name'),
dataIndex: 'name',
@ -32,31 +46,17 @@ export function getDataColumns(): BasicColumn[] {
width: 180,
sorter: true,
},
{
title: L('Required'),
dataIndex: 'required',
align: 'left',
width: 200,
sorter: true,
},
{
title: L('Enabled'),
dataIndex: 'enabled',
align: 'left',
width: 200,
sorter: true,
},
{
title: L('Emphasize'),
dataIndex: 'emphasize',
align: 'left',
align: 'center',
width: 200,
sorter: true,
},
{
title: L('ShowInDiscoveryDocument'),
dataIndex: 'showInDiscoveryDocument',
align: 'left',
align: 'center',
width: 200,
sorter: true,
},

17
apps/vue/src/views/identity-server/api-scopes/hooks/useModal.ts

@ -1,8 +1,8 @@
import type { Ref } from 'vue';
import { computed, ref, reactive, unref, watch } from 'vue';
import { message } from 'ant-design-vue';
import { cloneDeep } from 'lodash-es';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useValidation } from '/@/hooks/abp/useValidation';
@ -16,6 +16,7 @@ interface UseModal {
}
export function useModal({ modelIdRef, formElRef, tabActivedKey }: UseModal) {
const { createMessage } = useMessage();
const { L } = useLocalization('AbpIdentityServer');
const { ruleCreator } = useValidation();
const modelRef = ref<ApiScope>({} as ApiScope);
@ -76,14 +77,12 @@ export function useModal({ modelIdRef, formElRef, tabActivedKey }: UseModal) {
const api = isEdit.value
? update(input.id, Object.assign(input))
: create(Object.assign(input));
api
.then((res) => {
message.success(L('Successful'));
resolve(res);
})
.catch((error) => {
reject(error);
});
api.then((res) => {
createMessage.success(L('Successful'));
resolve(res);
}).catch((error) => {
reject(error);
});
})
.catch((error) => {
reject(error);

81
apps/vue/src/views/identity-server/clients/components/ClientApiResource.vue

@ -2,60 +2,49 @@
<Resources :resources="resources" :targetResources="targetResources" @change="handleChange" />
</template>
<script lang="ts">
import { computed, defineComponent, ref, onMounted, toRefs } from 'vue';
<script lang="ts" setup>
import { computed, ref, onMounted, toRefs } from 'vue';
import Resources from './Resources.vue';
import { getAssignableApiResources } from '/@/api/identity-server/clients';
import { Client } from '/@/api/identity-server/model/clientsModel';
import { useResource } from '../hooks/useResource';
export default defineComponent({
name: 'ClientApiResource',
components: { Resources },
props: {
modelRef: {
type: Object as PropType<Client>,
required: true,
},
const props = defineProps({
modelRef: {
type: Object as PropType<Client>,
required: true,
},
setup(props) {
const resources = ref<{ key: string; title: string }[]>([]);
const targetResources = computed(() => {
const targetScopes = resources.value.filter((item) =>
props.modelRef.allowedScopes.some((scope) => scope.scope === item.key),
);
return targetScopes.map((item) => item.key);
});
});
onMounted(() => {
getAssignableApiResources().then((res) => {
resources.value = res.items.map((item) => {
return {
key: item,
title: item,
};
});
});
});
const { handleResourceChange } = useResource({ modelRef: toRefs(props).modelRef });
const resources = ref<{ key: string; title: string }[]>([]);
const targetResources = computed(() => {
const targetScopes = resources.value.filter((item) =>
props.modelRef.allowedScopes.some((scope) => scope.scope === item.key),
);
function handleChange(_, direction, moveKeys: string[]) {
switch (direction) {
case 'left':
handleResourceChange('delete', moveKeys);
break;
case 'right':
handleResourceChange('add', moveKeys);
break;
}
}
return targetScopes.map((item) => item.key);
});
return {
resources,
targetResources,
handleChange,
};
},
onMounted(() => {
getAssignableApiResources().then((res) => {
resources.value = res.items.map((item) => {
return {
key: item,
title: item,
};
});
});
});
const { handleResourceChange } = useResource({ modelRef: toRefs(props).modelRef });
function handleChange(_, direction, moveKeys: string[]) {
switch (direction) {
case 'left':
handleResourceChange('delete', moveKeys);
break;
case 'right':
handleResourceChange('add', moveKeys);
break;
}
}
</script>

79
apps/vue/src/views/identity-server/clients/components/ClientCallback.vue

@ -10,60 +10,47 @@
/>
</template>
<script lang="ts">
import { defineComponent, toRefs } from 'vue';
<script lang="ts" setup>
import { toRefs } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { FormSchema } from '/@/components/Form';
import { BasicColumn } from '/@/components/Table';
import { Client } from '/@/api/identity-server/model/clientsModel';
import DynamicForm from './DynamicForm.vue';
import { useUrl } from '../hooks/useUrl';
import DynamicForm from './DynamicForm.vue';
export default defineComponent({
name: 'ClientCallback',
components: { DynamicForm },
props: {
modelRef: {
type: Object as PropType<Client>,
required: true,
},
const props = defineProps({
modelRef: {
type: Object as PropType<Client>,
required: true,
},
setup(props) {
const { L } = useLocalization('AbpIdentityServer');
const schemas: FormSchema[] = [
{
field: 'redirectUri',
component: 'Input',
label: 'Url',
colProps: { span: 24 },
required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'redirectUri',
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleRedirectUriChange } = useUrl({ modelRef: toRefs(props).modelRef });
});
function handleAddNew(record) {
handleRedirectUriChange('add', record.redirectUri);
}
const { L } = useLocalization('AbpIdentityServer');
const schemas: FormSchema[] = [
{
field: 'redirectUri',
component: 'Input',
label: 'Url',
colProps: { span: 24 },
required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'redirectUri',
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleRedirectUriChange } = useUrl({ modelRef: toRefs(props).modelRef });
function handleDelete(record) {
handleRedirectUriChange('delete', record.redirectUri);
}
function handleAddNew(record) {
handleRedirectUriChange('add', record.redirectUri);
}
return {
L,
schemas,
columns,
handleAddNew,
handleDelete,
};
},
});
function handleDelete(record) {
handleRedirectUriChange('delete', record.redirectUri);
}
</script>

130
apps/vue/src/views/identity-server/clients/components/ClientClaim.vue

@ -26,87 +26,75 @@
/>
</template>
<script lang="ts">
import { defineComponent, toRefs } from 'vue';
<script lang="ts" setup>
import { toRefs } from 'vue';
import { Checkbox, Form } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { FormSchema } from '/@/components/Form';
import { BasicColumn } from '/@/components/Table';
import DynamicForm from './DynamicForm.vue';
import { useClaim } from '../hooks/useClaim';
import { Client } from '/@/api/identity-server/model/clientsModel';
import { getActivedList } from '/@/api/identity/claim';
import DynamicForm from './DynamicForm.vue';
export default defineComponent({
name: 'ClientClaim',
components: { Checkbox, DynamicForm, FormItem: Form.Item },
props: {
modelRef: {
type: Object as PropType<Client>,
required: true,
},
},
setup(props) {
const { L } = useLocalization('AbpIdentityServer');
const schemas: FormSchema[] = [
{
field: 'type',
component: 'ApiSelect',
label: L('Claims:Type'),
colProps: { span: 24 },
required: true,
componentProps: {
api: () => getActivedList(),
resultField: 'items',
labelField: 'name',
valueField: 'name',
},
},
{
field: 'value',
component: 'Input',
label: L('Claims:Value'),
colProps: { span: 24 },
required: true,
// TODO: type ValueType
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'type',
title: L('Claims:Type'),
align: 'left',
width: '150',
sorter: true,
},
{
dataIndex: 'value',
title: L('Claims:Value'),
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleClaimChange, handleCheckedChange } = useClaim({
modelRef: toRefs(props).modelRef,
});
function handleAddNew(record) {
handleClaimChange('add', record);
}
const FormItem = Form.Item;
function handleDelete(record) {
handleClaimChange('delete', record);
}
const props = defineProps({
modelRef: {
type: Object as PropType<Client>,
required: true,
},
});
return {
L,
schemas,
columns,
handleAddNew,
handleDelete,
handleCheckedChange,
};
const { L } = useLocalization('AbpIdentityServer');
const schemas: FormSchema[] = [
{
field: 'type',
component: 'ApiSelect',
label: L('Claims:Type'),
colProps: { span: 24 },
required: true,
componentProps: {
api: () => getActivedList(),
resultField: 'items',
labelField: 'name',
valueField: 'name',
},
},
{
field: 'value',
component: 'Input',
label: L('Claims:Value'),
colProps: { span: 24 },
required: true,
// TODO: type ValueType
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'type',
title: L('Claims:Type'),
align: 'left',
width: '150',
sorter: true,
},
{
dataIndex: 'value',
title: L('Claims:Value'),
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleClaimChange, handleCheckedChange } = useClaim({
modelRef: toRefs(props).modelRef,
});
function handleAddNew(record) {
handleClaimChange('add', record);
}
function handleDelete(record) {
handleClaimChange('delete', record);
}
</script>

278
apps/vue/src/views/identity-server/clients/components/ClientClone.vue

@ -12,157 +12,145 @@
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, ref, unref } from 'vue';
<script lang="ts" setup>
import { ref, unref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { message } from 'ant-design-vue';
import { BasicForm, useForm, FormActionType, FormSchema } from '/@/components/Form';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { clone } from '/@/api/identity-server/clients';
export default defineComponent({
name: 'ClientClone',
components: { BasicForm, BasicModal },
emits: ['change', 'register'],
setup(_, { emit }) {
const { L } = useLocalization('AbpIdentityServer');
const clientIdRef = ref('');
const formElRef = ref<Nullable<FormActionType>>(null);
const formSchemas: FormSchema[] = [
{
field: 'clientId',
component: 'Input',
label: L('Client:Id'),
colProps: { span: 24 },
required: true,
},
{
field: 'clientName',
component: 'Input',
label: L('Name'),
colProps: { span: 24 },
required: true,
},
{
field: 'description',
component: 'InputTextArea',
label: L('Description'),
colProps: { span: 24 },
},
{
field: 'copyAllowedGrantType',
component: 'Checkbox',
label: L('Clone:CopyAllowedGrantType'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyAllowedGrantType'),
},
{
field: 'copyRedirectUri',
component: 'Checkbox',
label: L('Clone:CopyRedirectUri'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyRedirectUri'),
},
{
field: 'copyAllowedScope',
component: 'Checkbox',
defaultValue: true,
label: L('Clone:CopyAllowedScope'),
labelWidth: 180,
colProps: { span: 24 },
renderComponentContent: L('Clone:CopyAllowedScope'),
},
{
field: 'copyClaim',
component: 'Checkbox',
label: L('Clone:CopyClaim'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyClaim'),
},
{
field: 'copySecret',
component: 'Checkbox',
label: L('Clone:CopySecret'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopySecret'),
},
{
field: 'copyAllowedCorsOrigin',
component: 'Checkbox',
label: L('Clone:CopyAllowedCorsOrigin'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyAllowedCorsOrigin'),
},
{
field: 'copyPostLogoutRedirectUri',
component: 'Checkbox',
label: L('Clone:CopyPostLogoutRedirectUri'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyPostLogoutRedirectUri'),
},
{
field: 'copyProperties',
component: 'Checkbox',
label: L('Clone:CopyProperties'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyProperties'),
},
{
field: 'copyIdentityProviderRestriction',
component: 'Checkbox',
defaultValue: true,
label: L('Clone:CopyIdentityProviderRestriction'),
labelWidth: 180,
colProps: { span: 24 },
renderComponentContent: L('Clone:CopyIdentityProviderRestriction'),
},
];
const [registerForm] = useForm({
labelWidth: 120,
schemas: formSchemas,
showActionButtonGroup: false,
});
const [registerModal, { closeModal, changeOkLoading }] = useModalInner((data) => {
clientIdRef.value = data.id;
});
const emits = defineEmits(['change', 'register']);
function handleSubmit() {
const formEl = unref(formElRef);
formEl?.validate().then((input) => {
changeOkLoading(true);
clone(unref(clientIdRef), input)
.then(() => {
message.success(L('Successful'));
emit('change');
closeModal();
})
.finally(() => {
changeOkLoading(false);
});
});
}
return {
L,
formElRef,
registerModal,
registerForm,
handleSubmit,
};
const { createMessage } = useMessage();
const { L } = useLocalization('AbpIdentityServer');
const clientIdRef = ref('');
const formElRef = ref<Nullable<FormActionType>>(null);
const formSchemas: FormSchema[] = [
{
field: 'clientId',
component: 'Input',
label: L('Client:Id'),
colProps: { span: 24 },
required: true,
},
{
field: 'clientName',
component: 'Input',
label: L('Name'),
colProps: { span: 24 },
required: true,
},
{
field: 'description',
component: 'InputTextArea',
label: L('Description'),
colProps: { span: 24 },
},
{
field: 'copyAllowedGrantType',
component: 'Checkbox',
label: L('Clone:CopyAllowedGrantType'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyAllowedGrantType'),
},
{
field: 'copyRedirectUri',
component: 'Checkbox',
label: L('Clone:CopyRedirectUri'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyRedirectUri'),
},
{
field: 'copyAllowedScope',
component: 'Checkbox',
defaultValue: true,
label: L('Clone:CopyAllowedScope'),
labelWidth: 180,
colProps: { span: 24 },
renderComponentContent: L('Clone:CopyAllowedScope'),
},
{
field: 'copyClaim',
component: 'Checkbox',
label: L('Clone:CopyClaim'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyClaim'),
},
{
field: 'copySecret',
component: 'Checkbox',
label: L('Clone:CopySecret'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopySecret'),
},
{
field: 'copyAllowedCorsOrigin',
component: 'Checkbox',
label: L('Clone:CopyAllowedCorsOrigin'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyAllowedCorsOrigin'),
},
{
field: 'copyPostLogoutRedirectUri',
component: 'Checkbox',
label: L('Clone:CopyPostLogoutRedirectUri'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyPostLogoutRedirectUri'),
},
{
field: 'copyProperties',
component: 'Checkbox',
label: L('Clone:CopyProperties'),
labelWidth: 180,
colProps: { span: 24 },
defaultValue: true,
renderComponentContent: L('Clone:CopyProperties'),
},
{
field: 'copyIdentityProviderRestriction',
component: 'Checkbox',
defaultValue: true,
label: L('Clone:CopyIdentityProviderRestriction'),
labelWidth: 180,
colProps: { span: 24 },
renderComponentContent: L('Clone:CopyIdentityProviderRestriction'),
},
];
const [registerForm] = useForm({
labelWidth: 120,
schemas: formSchemas,
showActionButtonGroup: false,
});
const [registerModal, { closeModal, changeOkLoading }] = useModalInner((data) => {
clientIdRef.value = data.id;
});
function handleSubmit() {
const formEl = unref(formElRef);
formEl?.validate().then((input) => {
changeOkLoading(true);
clone(unref(clientIdRef), input)
.then(() => {
createMessage.success(L('Successful'));
emits('change');
closeModal();
})
.finally(() => {
changeOkLoading(false);
});
});
}
</script>

77
apps/vue/src/views/identity-server/clients/components/ClientCorsOrigins.vue

@ -10,8 +10,8 @@
/>
</template>
<script lang="ts">
import { defineComponent, toRefs } from 'vue';
<script lang="ts" setup>
import { toRefs } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { FormSchema } from '/@/components/Form';
import { BasicColumn } from '/@/components/Table';
@ -19,51 +19,38 @@
import DynamicForm from './DynamicForm.vue';
import { useUrl } from '../hooks/useUrl';
export default defineComponent({
name: 'ClientCorsOrigins',
components: { DynamicForm },
props: {
modelRef: {
type: Object as PropType<Client>,
required: true,
},
const props = defineProps({
modelRef: {
type: Object as PropType<Client>,
required: true,
},
setup(props) {
const { L } = useLocalization('AbpIdentityServer');
const schemas: FormSchema[] = [
{
field: 'origin',
component: 'Input',
label: 'Url',
colProps: { span: 24 },
required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'origin',
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleCorsOriginsChange } = useUrl({ modelRef: toRefs(props).modelRef });
});
function handleAddNew(record) {
handleCorsOriginsChange('add', record.origin);
}
const { L } = useLocalization('AbpIdentityServer');
const schemas: FormSchema[] = [
{
field: 'origin',
component: 'Input',
label: 'Url',
colProps: { span: 24 },
required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'origin',
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleCorsOriginsChange } = useUrl({ modelRef: toRefs(props).modelRef });
function handleDelete(record) {
handleCorsOriginsChange('delete', record.origin);
}
function handleAddNew(record) {
handleCorsOriginsChange('add', record.origin);
}
return {
L,
schemas,
columns,
handleAddNew,
handleDelete,
};
},
});
function handleDelete(record) {
handleCorsOriginsChange('delete', record.origin);
}
</script>

87
apps/vue/src/views/identity-server/clients/components/ClientGrantType.vue

@ -10,8 +10,8 @@
/>
</template>
<script lang="ts">
import { defineComponent, toRefs } from 'vue';
<script lang="ts" setup>
import { toRefs } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { FormSchema } from '/@/components/Form';
import { BasicColumn } from '/@/components/Table';
@ -19,56 +19,43 @@
import { useGrantType } from '../hooks/useGrantType';
import { Client } from '/@/api/identity-server/model/clientsModel';
export default defineComponent({
name: 'ClientGrantType',
components: { DynamicForm },
props: {
modelRef: {
type: Object as PropType<Client>,
required: true,
},
const props = defineProps({
modelRef: {
type: Object as PropType<Client>,
required: true,
},
setup(props) {
const { L } = useLocalization('AbpIdentityServer');
const { grantTypeOptions, handleGrantTypeChanged } = useGrantType({
modelRef: toRefs(props).modelRef,
});
const schemas: FormSchema[] = [
{
field: 'grantType',
component: 'Select',
label: L('Client:AllowedGrantTypes'),
colProps: { span: 24 },
required: true,
componentProps: {
options: grantTypeOptions,
},
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'grantType',
align: 'left',
width: 'auto',
sorter: true,
},
];
});
function handleAddNew(record) {
handleGrantTypeChanged('add', record);
}
const { L } = useLocalization('AbpIdentityServer');
const { grantTypeOptions, handleGrantTypeChanged } = useGrantType({
modelRef: toRefs(props).modelRef,
});
const schemas: FormSchema[] = [
{
field: 'grantType',
component: 'Select',
label: L('Client:AllowedGrantTypes'),
colProps: { span: 24 },
required: true,
componentProps: {
options: grantTypeOptions,
},
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'grantType',
align: 'left',
width: 'auto',
sorter: true,
},
];
function handleDelete(record) {
handleGrantTypeChanged('delete', record);
}
function handleAddNew(record) {
handleGrantTypeChanged('add', record);
}
return {
L,
schemas,
columns,
handleAddNew,
handleDelete,
};
},
});
function handleDelete(record) {
handleGrantTypeChanged('delete', record);
}
</script>

90
apps/vue/src/views/identity-server/clients/components/ClientIdentityProvider.vue

@ -16,67 +16,53 @@
/>
</template>
<script lang="ts">
import { defineComponent, toRefs } from 'vue';
<script lang="ts" setup>
import { toRefs } from 'vue';
import { Checkbox, Form } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { FormSchema } from '/@/components/Form';
import { BasicColumn } from '/@/components/Table';
import DynamicForm from './DynamicForm.vue';
import { useIdentityProvider } from '../hooks/useIdentityProvider';
import { Client } from '/@/api/identity-server/model/clientsModel';
import DynamicForm from './DynamicForm.vue';
export default defineComponent({
name: 'ClientIdentityProvider',
components: { Checkbox, DynamicForm, FormItem: Form.Item },
props: {
modelRef: {
type: Object as PropType<Client>,
required: true,
},
},
setup(props) {
const { L } = useLocalization('AbpIdentityServer');
const schemas: FormSchema[] = [
{
field: 'provider',
component: 'Input',
label: L('Client:IdentityProviderRestrictions'),
colProps: { span: 24 },
required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'provider',
title: L('Client:IdentityProviderRestrictions'),
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleIdpChange, handleCheckedChange } = useIdentityProvider({
modelRef: toRefs(props).modelRef,
});
function handleAddNew(record) {
console.log(record);
handleIdpChange('add', record);
}
const FormItem = Form.Item;
function handleDelete(record) {
console.log(record);
handleIdpChange('delete', record);
}
const props = defineProps({
modelRef: {
type: Object as PropType<Client>,
required: true,
},
});
return {
L,
schemas,
columns,
handleAddNew,
handleDelete,
handleCheckedChange,
};
const { L } = useLocalization('AbpIdentityServer');
const schemas: FormSchema[] = [
{
field: 'provider',
component: 'Input',
label: L('Client:IdentityProviderRestrictions'),
colProps: { span: 24 },
required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'provider',
title: L('Client:IdentityProviderRestrictions'),
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleIdpChange, handleCheckedChange } = useIdentityProvider({
modelRef: toRefs(props).modelRef,
});
function handleAddNew(record) {
handleIdpChange('add', record);
}
function handleDelete(record) {
handleIdpChange('delete', record);
}
</script>

83
apps/vue/src/views/identity-server/clients/components/ClientIdentityResource.vue

@ -2,60 +2,49 @@
<Resources :resources="resources" :targetResources="targetResources" @change="handleChange" />
</template>
<script lang="ts">
import { computed, defineComponent, ref, onMounted, toRefs } from 'vue';
import Resources from './Resources.vue';
<script lang="ts" setup>
import { computed, ref, onMounted, toRefs } from 'vue';
import { getAssignableIdentityResources } from '/@/api/identity-server/clients';
import { Client } from '/@/api/identity-server/model/clientsModel';
import { useResource } from '../hooks/useResource';
import Resources from './Resources.vue';
export default defineComponent({
name: 'ClientIdentityResource',
components: { Resources },
props: {
modelRef: {
type: Object as PropType<Client>,
required: true,
},
const props = defineProps({
modelRef: {
type: Object as PropType<Client>,
required: true,
},
setup(props) {
const resources = ref<{ key: string; title: string }[]>([]);
const targetResources = computed(() => {
const targetScopes = resources.value.filter((item) =>
props.modelRef.allowedScopes.some((scope) => scope.scope === item.key),
);
return targetScopes.map((item) => item.key);
});
});
onMounted(() => {
getAssignableIdentityResources().then((res) => {
resources.value = res.items.map((item) => {
return {
key: item,
title: item,
};
});
});
});
const { handleResourceChange } = useResource({ modelRef: toRefs(props).modelRef });
const resources = ref<{ key: string; title: string }[]>([]);
const targetResources = computed(() => {
const targetScopes = resources.value.filter((item) =>
props.modelRef.allowedScopes.some((scope) => scope.scope === item.key),
);
function handleChange(_, direction, moveKeys: string[]) {
switch (direction) {
case 'left':
handleResourceChange('delete', moveKeys);
break;
case 'right':
handleResourceChange('add', moveKeys);
break;
}
}
return targetScopes.map((item) => item.key);
});
return {
resources,
targetResources,
handleChange,
};
},
onMounted(() => {
getAssignableIdentityResources().then((res) => {
resources.value = res.items.map((item) => {
return {
key: item,
title: item,
};
});
});
});
const { handleResourceChange } = useResource({ modelRef: toRefs(props).modelRef });
function handleChange(_, direction, moveKeys: string[]) {
switch (direction) {
case 'left':
handleResourceChange('delete', moveKeys);
break;
case 'right':
handleResourceChange('add', moveKeys);
break;
}
}
</script>

79
apps/vue/src/views/identity-server/clients/components/ClientLogoutRedirectUris.vue

@ -10,60 +10,47 @@
/>
</template>
<script lang="ts">
import { defineComponent, toRefs } from 'vue';
<script lang="ts" setup>
import { toRefs } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { FormSchema } from '/@/components/Form';
import { BasicColumn } from '/@/components/Table';
import { Client } from '/@/api/identity-server/model/clientsModel';
import DynamicForm from './DynamicForm.vue';
import { useUrl } from '../hooks/useUrl';
import DynamicForm from './DynamicForm.vue';
export default defineComponent({
name: 'ClientLogoutRedirectUris',
components: { DynamicForm },
props: {
modelRef: {
type: Object as PropType<Client>,
required: true,
},
const props = defineProps({
modelRef: {
type: Object as PropType<Client>,
required: true,
},
setup(props) {
const { L } = useLocalization('AbpIdentityServer');
const schemas: FormSchema[] = [
{
field: 'postLogoutRedirectUri',
component: 'Input',
label: 'Url',
colProps: { span: 24 },
required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'postLogoutRedirectUri',
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleLogoutRedirectUris } = useUrl({ modelRef: toRefs(props).modelRef });
});
function handleAddNew(record) {
handleLogoutRedirectUris('add', record.postLogoutRedirectUri);
}
const { L } = useLocalization('AbpIdentityServer');
const schemas: FormSchema[] = [
{
field: 'postLogoutRedirectUri',
component: 'Input',
label: 'Url',
colProps: { span: 24 },
required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'postLogoutRedirectUri',
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleLogoutRedirectUris } = useUrl({ modelRef: toRefs(props).modelRef });
function handleDelete(record) {
handleLogoutRedirectUris('delete', record.postLogoutRedirectUri);
}
function handleAddNew(record) {
handleLogoutRedirectUris('add', record.postLogoutRedirectUri);
}
return {
L,
schemas,
columns,
handleAddNew,
handleDelete,
};
},
});
function handleDelete(record) {
handleLogoutRedirectUris('delete', record.postLogoutRedirectUri);
}
</script>

203
apps/vue/src/views/identity-server/clients/components/ClientModal.vue

@ -13,8 +13,8 @@
ref="formElRef"
:model="modelRef"
:rules="formRules"
:label-col="labelCol"
:wrapper-col="wrapperCol"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 18 }"
>
<Tabs
v-model:activeKey="tabActivedKey"
@ -74,18 +74,18 @@
</span>
<template #overlay>
<Menu @click="handleClickUrlsMenu">
<MenuItem key="client-callback">{{ L('Client:CallbackUrl') }}</MenuItem>
<MenuItem key="client-cors-origins">{{
<MenuItem key="ClientCallback">{{ L('Client:CallbackUrl') }}</MenuItem>
<MenuItem key="ClientCorsOrigins">{{
L('Client:AllowedCorsOrigins')
}}</MenuItem>
<MenuItem key="client-logout-redirect-uris">{{
<MenuItem key="ClientLogoutRedirectUris">{{
L('Client:PostLogoutRedirectUri')
}}</MenuItem>
</Menu>
</template>
</Dropdown>
</template>
<component :is="urlsComponent" :modelRef="modelRef" />
<component :is="componentsRef[urlsComponent]" :modelRef="modelRef" />
</TabPane>
<!-- 资源 -->
@ -98,13 +98,13 @@
</span>
<template #overlay>
<Menu @click="handleClickResourcesMenu">
<MenuItem key="client-api-resource">{{ L('Resource:Api') }}</MenuItem>
<MenuItem key="client-identity-resource">{{ L('Resource:Identity') }}</MenuItem>
<MenuItem key="ClientApiResource">{{ L('Resource:Api') }}</MenuItem>
<MenuItem key="ClientIdentityResource">{{ L('Resource:Identity') }}</MenuItem>
</Menu>
</template>
</Dropdown>
</template>
<component :is="resourcesComponent" :modelRef="modelRef" />
<component :is="componentsRef[resourcesComponent]" :modelRef="modelRef" />
</TabPane>
<!-- 认证/注销 -->
@ -256,27 +256,28 @@
</span>
<template #overlay>
<Menu @click="handleClickAdvancedMenu">
<MenuItem key="client-secret">{{ L('Secret') }}</MenuItem>
<MenuItem key="client-claim">{{ L('Claims') }}</MenuItem>
<MenuItem key="client-properties">{{ L('Propertites') }}</MenuItem>
<MenuItem key="client-grant-type">{{ L('Client:AllowedGrantTypes') }}</MenuItem>
<MenuItem key="client-identity-provider">{{
<MenuItem key="ClientSecret">{{ L('Secret') }}</MenuItem>
<MenuItem key="ClientClaim">{{ L('Claims') }}</MenuItem>
<MenuItem key="ClientProperties">{{ L('Propertites') }}</MenuItem>
<MenuItem key="ClientGrantType">{{ L('Client:AllowedGrantTypes') }}</MenuItem>
<MenuItem key="ClientIdentityProvider">{{
L('Client:IdentityProviderRestrictions')
}}</MenuItem>
</Menu>
</template>
</Dropdown>
</template>
<component :is="advancedComponent" :modelRef="modelRef" />
<component :is="componentsRef[advancedComponent]" :modelRef="modelRef" />
</TabPane>
</Tabs>
</Form>
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
<script lang="ts" setup>
import { ref, shallowRef } from 'vue';
import { useTabsStyle } from '/@/hooks/component/useStyles';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { DownOutlined } from '@ant-design/icons-vue';
import { Checkbox, Dropdown, Menu, Tabs, Form, Input, InputNumber, Select } from 'ant-design-vue';
@ -293,112 +294,78 @@
import ClientProperties from './ClientProperties.vue';
import ClientGrantType from './ClientGrantType.vue';
import ClientIdentityProvider from './ClientIdentityProvider.vue';
export default defineComponent({
name: 'ClientModal',
components: {
ClientCallback,
ClientCorsOrigins,
ClientLogoutRedirectUris,
ClientApiResource,
ClientIdentityResource,
ClientSecret,
ClientClaim,
ClientProperties,
ClientGrantType,
ClientIdentityProvider,
BasicModal,
DownOutlined,
Form,
FormItem: Form.Item,
Dropdown,
Menu,
MenuItem: Menu.Item,
Tabs,
TabPane: Tabs.TabPane,
BInput,
InputNumber,
TextArea: Input.TextArea,
Checkbox,
Select,
Option: Select.Option,
},
emits: ['change', 'register'],
setup(_, { emit }) {
const { L } = useLocalization('AbpIdentityServer');
const formElRef = ref<any>(null);
const modelIdRef = ref('');
const tabActivedKey = ref('basic');
const advancedComponent = ref('client-secret');
const urlsComponent = ref('client-callback');
const resourcesComponent = ref('client-api-resource');
const [registerModal, { changeOkLoading }] = useModalInner((val) => {
modelIdRef.value = val.id;
});
const {
isEdit,
modelRef,
formRules,
formTitle,
handleChangeTab,
handleVisibleModal,
handleSubmit,
} = useModal({
modelIdRef,
formElRef,
tabActivedKey,
});
const tabsStyle = useTabsStyle();
function handleClickAdvancedMenu(e) {
tabActivedKey.value = 'advanced';
advancedComponent.value = e.key;
}
const FormItem = Form.Item;
const MenuItem = Menu.Item;
const TabPane = Tabs.TabPane;
const TextArea = Input.TextArea;
const Option = Select.Option;
function handleClickUrlsMenu(e) {
tabActivedKey.value = 'urls';
urlsComponent.value = e.key;
}
function handleClickResourcesMenu(e) {
tabActivedKey.value = 'resources';
resourcesComponent.value = e.key;
}
const componentsRef = shallowRef({
'ClientCallback': ClientCallback,
'ClientCorsOrigins': ClientCorsOrigins,
'ClientLogoutRedirectUris': ClientLogoutRedirectUris,
'ClientApiResource': ClientApiResource,
'ClientIdentityResource': ClientIdentityResource,
'ClientSecret': ClientSecret,
'ClientClaim': ClientClaim,
'ClientProperties': ClientProperties,
'ClientGrantType': ClientGrantType,
'ClientIdentityProvider': ClientIdentityProvider,
});
function handleOk() {
changeOkLoading(true);
handleSubmit()
.then(() => {
emit('change');
})
.finally(() => {
changeOkLoading(false);
});
}
const emits = defineEmits(['change', 'register']);
return {
L,
isEdit,
formElRef,
formRules,
formTitle,
tabsStyle,
tabActivedKey,
registerModal,
modelRef,
labelCol: { span: 6 },
wrapperCol: { span: 18 },
advancedComponent,
urlsComponent,
resourcesComponent,
handleClickUrlsMenu,
handleClickResourcesMenu,
handleClickAdvancedMenu,
handleChangeTab,
handleVisibleModal,
handleOk,
};
},
const { createMessage } = useMessage();
const { L } = useLocalization('AbpIdentityServer');
const formElRef = ref<any>(null);
const modelIdRef = ref('');
const tabActivedKey = ref('basic');
const advancedComponent = ref('ClientSecret');
const urlsComponent = ref('ClientCallback');
const resourcesComponent = ref('ClientApiResource');
const [registerModal, { changeOkLoading }] = useModalInner((val) => {
modelIdRef.value = val.id;
});
const {
isEdit,
modelRef,
formRules,
formTitle,
handleChangeTab,
handleVisibleModal,
handleSubmit,
} = useModal({
modelIdRef,
formElRef,
tabActivedKey,
});
const tabsStyle = useTabsStyle();
function handleClickAdvancedMenu(e) {
tabActivedKey.value = 'advanced';
advancedComponent.value = e.key;
}
function handleClickUrlsMenu(e) {
tabActivedKey.value = 'urls';
urlsComponent.value = e.key;
}
function handleClickResourcesMenu(e) {
tabActivedKey.value = 'resources';
resourcesComponent.value = e.key;
}
function handleOk() {
changeOkLoading(true);
handleSubmit().then(() => {
createMessage.success(L('Successful'));
emits('change');
}).finally(() => {
changeOkLoading(false);
});
}
</script>
<style lang="less" scoped>

113
apps/vue/src/views/identity-server/clients/components/ClientProperties.vue

@ -11,77 +11,64 @@
/>
</template>
<script lang="ts">
import { defineComponent, toRefs } from 'vue';
<script lang="ts" setup>
import { toRefs } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { FormSchema } from '/@/components/Form';
import { BasicColumn } from '/@/components/Table';
import DynamicForm from './DynamicForm.vue';
import { useProperty } from '../hooks/useProperty';
import { Client } from '/@/api/identity-server/model/clientsModel';
import DynamicForm from './DynamicForm.vue';
export default defineComponent({
name: 'ClientProperties',
components: { DynamicForm },
props: {
modelRef: {
type: Object as PropType<Client>,
required: true,
},
const props = defineProps({
modelRef: {
type: Object as PropType<Client>,
required: true,
},
setup(props) {
const { L } = useLocalization('AbpIdentityServer');
const schemas: FormSchema[] = [
{
field: 'type',
component: 'Input',
label: L('Propertites:Key'),
colProps: { span: 24 },
required: true,
},
{
field: 'value',
component: 'Input',
label: L('Propertites:Value'),
colProps: { span: 24 },
required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'type',
title: L('Propertites:Key'),
align: 'left',
width: '150',
sorter: true,
},
{
dataIndex: 'value',
title: L('Propertites:Value'),
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleNewProperty, handleDeleteProperty } = useProperty({
modelRef: toRefs(props).modelRef,
});
function handleAddNew(record) {
handleNewProperty(record);
}
function handleDelete(record) {
handleDeleteProperty(record);
}
});
return {
L,
schemas,
columns,
handleAddNew,
handleDelete,
};
const { L } = useLocalization('AbpIdentityServer');
const schemas: FormSchema[] = [
{
field: 'type',
component: 'Input',
label: L('Propertites:Key'),
colProps: { span: 24 },
required: true,
},
{
field: 'value',
component: 'Input',
label: L('Propertites:Value'),
colProps: { span: 24 },
required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'type',
title: L('Propertites:Key'),
align: 'left',
width: '150',
sorter: true,
},
{
dataIndex: 'value',
title: L('Propertites:Value'),
align: 'left',
width: 'auto',
sorter: true,
},
];
const { handleNewProperty, handleDeleteProperty } = useProperty({
modelRef: toRefs(props).modelRef,
});
function handleAddNew(record) {
handleNewProperty(record);
}
function handleDelete(record) {
handleDeleteProperty(record);
}
</script>

206
apps/vue/src/views/identity-server/clients/components/ClientSecret.vue

@ -16,126 +16,114 @@
/>
</template>
<script lang="ts">
import { defineComponent, toRefs } from 'vue';
<script lang="ts" setup>
import { toRefs } from 'vue';
import { Checkbox, Form } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { FormSchema } from '/@/components/Form';
import { BasicColumn } from '/@/components/Table';
import { formatToDateTime } from '/@/utils/dateUtil';
import { Client } from '/@/api/identity-server/model/clientsModel';
import DynamicForm from './DynamicForm.vue';
import { useSecret } from '../hooks/useSecret';
import DynamicForm from './DynamicForm.vue';
export default defineComponent({
name: 'ClientSecret',
components: { Checkbox, DynamicForm, FormItem: Form.Item },
props: {
modelRef: {
type: Object as PropType<Client>,
required: true,
const FormItem = Form.Item;
const props = defineProps({
modelRef: {
type: Object as PropType<Client>,
required: true,
},
});
const { L } = useLocalization('AbpIdentityServer');
const schemas: FormSchema[] = [
{
field: 'type',
component: 'Select',
label: L('Secret:Type'),
colProps: { span: 24 },
required: true,
componentProps: {
options: [
{ label: 'JsonWebKey', value: 'JWK' },
{ label: 'SharedSecret', value: 'SharedSecret' },
{ label: 'X509CertificateName', value: 'X509Name' },
{ label: 'X509CertificateBase64', value: 'X509CertificateBase64' },
{ label: 'X509CertificateThumbprint', value: 'X509Thumbprint' },
],
},
},
setup(props) {
const { L } = useLocalization('AbpIdentityServer');
const schemas: FormSchema[] = [
{
field: 'type',
component: 'Select',
label: L('Secret:Type'),
colProps: { span: 24 },
required: true,
componentProps: {
options: [
{ label: 'JsonWebKey', value: 'JWK' },
{ label: 'SharedSecret', value: 'SharedSecret' },
{ label: 'X509CertificateName', value: 'X509Name' },
{ label: 'X509CertificateBase64', value: 'X509CertificateBase64' },
{ label: 'X509CertificateThumbprint', value: 'X509Thumbprint' },
],
},
},
{
field: 'value',
component: 'Input',
label: L('Secret:Value'),
colProps: { span: 24 },
required: true,
},
{
field: 'description',
component: 'InputTextArea',
label: L('Description'),
colProps: { span: 24 },
},
{
field: 'expiration',
component: 'DatePicker',
label: L('Expiration'),
colProps: { span: 24 },
componentProps: {
style: {
width: '100%',
},
},
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'type',
title: L('Secret:Type'),
align: 'left',
width: '120',
sorter: true,
},
{
dataIndex: 'value',
title: L('Secret:Value'),
align: 'left',
width: 'auto',
sorter: true,
},
{
dataIndex: 'description',
title: L('Description'),
align: 'left',
width: '100',
sorter: true,
},
{
dataIndex: 'expiration',
title: L('Expiration'),
align: 'left',
width: '100',
sorter: true,
format: (text) => {
if (text) {
return formatToDateTime(text);
}
return '';
},
{
field: 'value',
component: 'Input',
label: L('Secret:Value'),
colProps: { span: 24 },
required: true,
},
{
field: 'description',
component: 'InputTextArea',
label: L('Description'),
colProps: { span: 24 },
},
{
field: 'expiration',
component: 'DatePicker',
label: L('Expiration'),
colProps: { span: 24 },
componentProps: {
style: {
width: '100%',
},
];
const { handleSecretChange, handleRequiredChange } = useSecret({
modelRef: toRefs(props).modelRef,
});
function handleAddNew(record) {
handleSecretChange('add', record);
}
function handleDelete(record) {
handleSecretChange('delete', record);
}
return {
L,
schemas,
columns,
handleAddNew,
handleDelete,
handleRequiredChange,
};
},
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'type',
title: L('Secret:Type'),
align: 'left',
width: '120',
sorter: true,
},
{
dataIndex: 'value',
title: L('Secret:Value'),
align: 'left',
width: 'auto',
sorter: true,
},
{
dataIndex: 'description',
title: L('Description'),
align: 'left',
width: '100',
sorter: true,
},
{
dataIndex: 'expiration',
title: L('Expiration'),
align: 'left',
width: '100',
sorter: true,
format: (text) => {
if (text) {
return formatToDateTime(text);
}
return '';
},
},
];
const { handleSecretChange, handleRequiredChange } = useSecret({
modelRef: toRefs(props).modelRef,
});
function handleAddNew(record) {
handleSecretChange('add', record);
}
function handleDelete(record) {
handleSecretChange('delete', record);
}
</script>

155
apps/vue/src/views/identity-server/clients/components/ClientTable.vue

@ -6,7 +6,8 @@
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'enabled'">
<Switch :checked="record.enabled" readonly />
<CheckOutlined v-if="record.enabled" class="enable" />
<CloseOutlined v-else class="disable" />
</template>
<template v-else-if="column.key === 'actions'">
<TableAction
@ -47,9 +48,10 @@
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { Button, Modal, Switch } from 'ant-design-vue';
<script lang="ts" setup>
import { Button } from 'ant-design-vue';
import { CheckOutlined, CloseOutlined } from '@ant-design/icons-vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicTable, TableAction, useTable } from '/@/components/Table';
import { useModal } from '/@/components/Modal';
@ -57,100 +59,75 @@
import { getSearchFormSchemas } from '../datas/ModalData';
import { deleteById, getList } from '/@/api/identity-server/clients';
import { formatPagedRequest } from '/@/utils/http/abp/helper';
import { PermissionModal } from '/@/components/Permission';
import ClientModal from './ClientModal.vue';
import ClientClone from './ClientClone.vue';
import { PermissionModal } from '/@/components/Permission';
export default defineComponent({
name: 'ApiScopeTable',
components: {
ClientModal,
ClientClone,
BasicTable,
Button,
Switch,
TableAction,
PermissionModal,
const { createMessage, createConfirm } = useMessage();
const { L } = useLocalization('AbpIdentityServer');
const [registerModal, { openModal, closeModal }] = useModal();
const [registerCloneModal, { openModal: openCloneModal }] = useModal();
const [registerPermissionModal, { openModal: openPermissionModal }] = useModal();
const [registerTable, { reload }] = useTable({
rowKey: 'id',
title: L('DisplayName:ApiScopes'),
columns: getDataColumns(),
api: getList,
beforeFetch: formatPagedRequest,
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: true,
immediate: true,
canColDrag: true,
formConfig: getSearchFormSchemas(),
actionColumn: {
width: 200,
title: L('Actions'),
dataIndex: 'actions',
},
setup() {
const { L } = useLocalization('AbpIdentityServer');
const [registerModal, { openModal, closeModal }] = useModal();
const [registerCloneModal, { openModal: openCloneModal }] = useModal();
const [registerPermissionModal, { openModal: openPermissionModal }] = useModal();
const [registerTable, { reload }] = useTable({
rowKey: 'id',
title: L('DisplayName:ApiScopes'),
columns: getDataColumns(),
api: getList,
beforeFetch: formatPagedRequest,
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: true,
immediate: true,
canColDrag: true,
formConfig: getSearchFormSchemas(),
actionColumn: {
width: 200,
title: L('Actions'),
dataIndex: 'actions',
},
});
});
function handleAddNew() {
openModal(true, {});
}
function handleAddNew() {
openModal(true, {});
}
function handleEdit(record) {
openModal(true, record);
}
function handleEdit(record) {
openModal(true, record);
}
function handleChange() {
closeModal();
reload();
}
function handleChange() {
closeModal();
reload();
}
function handleClone(record) {
openCloneModal(true, record);
}
function handleClone(record) {
openCloneModal(true, record);
}
function handlePermission(record) {
const props = {
providerName: 'C',
providerKey: record.clientId,
};
openPermissionModal(true, props, true);
}
function handlePermission(record) {
const props = {
providerName: 'C',
providerKey: record.clientId,
};
openPermissionModal(true, props, true);
}
function handleDelete(record) {
Modal.warning({
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
reload();
});
},
function handleDelete(record) {
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reload();
});
}
return {
L,
registerModal,
registerTable,
handleAddNew,
handleDelete,
handleEdit,
handleChange,
handleClone,
registerCloneModal,
handlePermission,
registerPermissionModal,
};
},
});
},
});
}
</script>

181
apps/vue/src/views/identity-server/clients/components/DynamicForm.vue

@ -21,113 +21,100 @@
</div>
</template>
<script lang="ts">
import { defineComponent, ref, watch } from 'vue';
<script lang="ts" setup>
import { ref, watch } from 'vue';
import { BasicTitle } from '/@/components/Basic';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicForm, FormSchema, useForm } from '/@/components/Form';
import { BasicTable, BasicColumn, TableAction, useTable } from '/@/components/Table';
export default defineComponent({
name: 'DynamicForm',
components: { BasicForm, BasicTitle, BasicTable, TableAction },
props: {
schemas: {
type: [Array] as PropType<FormSchema[]>,
required: true,
default: () => [],
},
labelWidth: {
type: Number,
},
columns: {
type: [Array] as PropType<BasicColumn[]>,
required: true,
default: () => [],
},
dataSource: {
type: [Array] as PropType<Recordable[]>,
required: true,
default: () => [],
},
rowKey: {
type: String,
default: () => 'id',
},
showHeader: {
type: Boolean,
default: () => false,
},
title: {
type: String,
default: () => '',
},
tableTitle: {
type: String,
default: () => '',
},
const emits = defineEmits(['new', 'delete']);
const props = defineProps({
schemas: {
type: [Array] as PropType<FormSchema[]>,
required: true,
default: () => [],
},
emits: ['new', 'delete'],
setup(props, { emit }) {
const { L } = useLocalization('AbpIdentityServer');
const modelRef = ref({});
const [registerForm, { resetFields }] = useForm({
model: modelRef,
labelWidth: props.labelWidth,
schemas: props.schemas,
showResetButton: false,
submitButtonOptions: {
text: L('AddNew'),
// icon: 'ant-design:plus-outlined',
},
});
const [registerTable, { setTableData }] = useTable({
rowKey: props.rowKey,
showHeader: props.showHeader,
title: props.tableTitle,
columns: props.columns,
dataSource: props.dataSource,
pagination: false,
striped: false,
useSearchForm: false,
showTableSetting: false,
showIndexColumn: false,
bordered: false,
actionColumn: {
width: 200,
title: L('Actions'),
dataIndex: 'action',
},
});
labelWidth: {
type: Number,
},
columns: {
type: [Array] as PropType<BasicColumn[]>,
required: true,
default: () => [],
},
dataSource: {
type: [Array] as PropType<Recordable[]>,
required: true,
default: () => [],
},
rowKey: {
type: String,
default: () => 'id',
},
showHeader: {
type: Boolean,
default: () => false,
},
title: {
type: String,
default: () => '',
},
tableTitle: {
type: String,
default: () => '',
},
});
watch(
() => props.dataSource,
(data) => {
setTableData(data);
},
{
deep: true,
},
);
const { L } = useLocalization('AbpIdentityServer');
const modelRef = ref({});
const [registerForm, { resetFields }] = useForm({
model: modelRef,
labelWidth: props.labelWidth,
schemas: props.schemas,
showResetButton: false,
submitButtonOptions: {
text: L('AddNew'),
// icon: 'ant-design:plus-outlined',
},
});
const [registerTable, { setTableData }] = useTable({
rowKey: props.rowKey,
showHeader: props.showHeader,
title: props.tableTitle,
columns: props.columns,
dataSource: props.dataSource,
pagination: false,
striped: false,
useSearchForm: false,
showTableSetting: false,
showIndexColumn: false,
bordered: false,
actionColumn: {
width: 200,
title: L('Actions'),
dataIndex: 'action',
},
});
function handleSubmit(input) {
emit('new', input);
resetFields();
}
watch(
() => props.dataSource,
(data) => {
setTableData(data);
},
{
deep: true,
},
);
function handleDelete(record) {
emit('delete', record);
}
function handleSubmit(input) {
emits('new', input);
resetFields();
}
return {
L,
registerForm,
registerTable,
handleSubmit,
handleDelete,
};
},
});
function handleDelete(record) {
emits('delete', record);
}
</script>
<style lang="less" scoped>

59
apps/vue/src/views/identity-server/clients/components/Resources.vue

@ -9,46 +9,33 @@
/>
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue';
<script lang="ts" setup>
import { computed } from 'vue';
import { Transfer } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
export default defineComponent({
name: 'Resources',
components: { Transfer },
props: {
resources: {
type: [Array] as PropType<{ key: string; title: string }[]>,
required: true,
default: () => [],
},
targetResources: { type: [Array] as PropType<string[]>, required: true, default: () => [] },
listStyle: { type: Object, required: false },
const emits = defineEmits(['change']);
const props = defineProps({
resources: {
type: [Array] as PropType<{ key: string; title: string }[]>,
required: true,
default: () => [],
},
emits: ['change'],
setup(props, { emit }) {
const { L } = useLocalization('AbpIdentityServer');
const defaultListStyle = {
width: '48%',
height: '500px',
minHeight: '500px',
};
const getListStyle = computed(() => {
return {...defaultListStyle, ...props.listStyle}
});
function handleChange(targetKeys, direction, moveKeys) {
emit('change', targetKeys, direction, moveKeys);
}
targetResources: { type: [Array] as PropType<string[]>, required: true, default: () => [] },
listStyle: { type: Object, required: false },
});
return {
L,
getListStyle,
handleChange,
};
},
const { L } = useLocalization('AbpIdentityServer');
const defaultListStyle = {
width: '48%',
height: '500px',
minHeight: '500px',
};
const getListStyle = computed(() => {
return {...defaultListStyle, ...props.listStyle}
});
function handleChange(targetKeys, direction, moveKeys) {
emits('change', targetKeys, direction, moveKeys);
}
</script>

32
apps/vue/src/views/identity-server/clients/hooks/useModal.ts

@ -1,8 +1,8 @@
import type { Ref } from 'vue';
import { computed, ref, reactive, unref, watch } from 'vue';
import { message } from 'ant-design-vue';
import { cloneDeep } from 'lodash-es';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useValidation } from '/@/hooks/abp/useValidation';
@ -16,6 +16,7 @@ interface UseModal {
}
export function useModal({ modelIdRef, formElRef, tabActivedKey }: UseModal) {
const { createMessage } = useMessage();
const { L } = useLocalization('AbpIdentityServer');
const { ruleCreator } = useValidation();
const modelRef = ref<Client>({} as Client);
@ -89,25 +90,20 @@ export function useModal({ modelIdRef, formElRef, tabActivedKey }: UseModal) {
function handleSubmit() {
return new Promise<any>((resolve, reject) => {
const formEl = unref(formElRef);
formEl
.validate()
.then(() => {
const input = cloneDeep(unref(modelRef));
const api = isEdit.value
? update(input.id, Object.assign(input))
: create(Object.assign(input));
api
.then((res) => {
message.success(L('Successful'));
resolve(res);
})
.catch((error) => {
reject(error);
});
})
.catch((error) => {
formEl.validate().then(() => {
const input = cloneDeep(unref(modelRef));
const api = isEdit.value
? update(input.id, Object.assign(input))
: create(Object.assign(input));
api.then((res) => {
createMessage.success(L('Successful'));
resolve(res);
}).catch((error) => {
reject(error);
});
}).catch((error) => {
reject(error);
});
});
}

86
apps/vue/src/views/identity-server/components/Properties.vue

@ -2,7 +2,7 @@
<div>
<BasicTable
rowKey="key"
:columns="columns"
:columns="getDataColumns()"
:dataSource="properties"
:pagination="false"
:showTableSetting="true"
@ -38,8 +38,8 @@
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
<script lang="ts" setup>
import { ref } from 'vue';
import { Button } from 'ant-design-vue';
import { BasicForm, useForm } from '/@/components/Form';
import { BasicModal, useModal } from '/@/components/Modal';
@ -49,60 +49,38 @@
import { getDataColumns } from './TableData';
import { getFormSchemas } from './ModalData';
export default defineComponent({
name: 'Properties',
components: {
BasicForm,
BasicModal,
BasicTable,
Button,
TableAction,
const emits = defineEmits(['new', 'props-new', 'props-delete']);
defineProps({
properties: {
type: [Array] as PropType<Property[]>,
required: true,
default: () => [],
},
props: {
properties: {
type: [Array] as PropType<Property[]>,
required: true,
default: () => [],
},
},
emits: ['new', 'props-new', 'props-delete'],
setup(_, { emit }) {
const { L } = useLocalization('AbpIdentityServer');
const title = ref('');
const [registerForm, { validate, resetFields }] = useForm({
labelWidth: 120,
showActionButtonGroup: false,
schemas: getFormSchemas(),
});
const [registerModal, { openModal, closeModal }] = useModal();
});
function handleAddNew() {
title.value = L('Propertites:New');
openModal(true);
}
const { L } = useLocalization('AbpIdentityServer');
const title = ref('');
const [registerForm, { validate, resetFields }] = useForm({
labelWidth: 120,
showActionButtonGroup: false,
schemas: getFormSchemas(),
});
const [registerModal, { openModal, closeModal }] = useModal();
function handleDelete(record) {
emit('props-delete', record);
}
function handleAddNew() {
title.value = L('Propertites:New');
openModal(true);
}
function handleSubmit() {
validate().then((input) => {
emit('props-new', input);
resetFields();
closeModal();
});
}
function handleDelete(record) {
emits('props-delete', record);
}
return {
L,
title,
handleAddNew,
handleDelete,
handleSubmit,
columns: getDataColumns(),
registerForm,
registerModal,
};
},
});
function handleSubmit() {
validate().then((input) => {
emits('props-new', input);
resetFields();
closeModal();
});
}
</script>

87
apps/vue/src/views/identity-server/components/UserClaim.vue

@ -9,59 +9,54 @@
/>
</template>
<script lang="ts">
import { computed, defineComponent, onMounted, ref } from 'vue';
<script lang="ts" setup>
import { computed, onMounted, ref } from 'vue';
import { Transfer } from 'ant-design-vue';
import { getActivedList } from '/@/api/identity/claim';
import { useLocalization } from '/@/hooks/abp/useLocalization';
export default defineComponent({
name: 'UserClaim',
components: { Transfer },
props: {
targetClaims: { type: [Array] as PropType<string[]>, required: true, default: () => [] },
listStyle: { type: Object, required: false },
const emits = defineEmits(['change']);
const props = defineProps({
targetClaims: {
type: [Array] as PropType<string[]>,
required: true,
default: () => [],
},
emits: ['change'],
setup(props, { emit }) {
const { L } = useLocalization('AbpIdentityServer');
const userClaims = ref<
{
key: string;
title: string;
}[]
>([]);
const defaultListStyle = {
width: '48%',
height: '500px',
minHeight: '500px',
};
const getListStyle = computed(() => {
return {...defaultListStyle, ...props.listStyle}
});
listStyle: {
type: Object,
required: false,
},
});
onMounted(() => {
getActivedList().then((res) => {
userClaims.value = res.items.map((item) => {
return {
key: item.name,
title: item.name,
};
});
});
});
const { L } = useLocalization('AbpIdentityServer');
const userClaims = ref<
{
key: string;
title: string;
}[]
>([]);
const defaultListStyle = {
width: '48%',
height: '500px',
minHeight: '500px',
};
function handleChange(targetKeys, direction, moveKeys) {
emit('change', targetKeys, direction, moveKeys);
}
const getListStyle = computed(() => {
return {...defaultListStyle, ...props.listStyle}
});
return {
L,
getListStyle,
userClaims,
handleChange,
};
},
onMounted(() => {
getActivedList().then((res) => {
userClaims.value = res.items.map((item) => {
return {
key: item.name,
title: item.name,
};
});
});
});
function handleChange(targetKeys, direction, moveKeys) {
emits('change', targetKeys, direction, moveKeys);
}
</script>

140
apps/vue/src/views/identity-server/identity-resources/components/IdentityResourceModal.vue

@ -13,8 +13,8 @@
ref="formElRef"
:model="modelRef"
:rules="formRules"
:label-col="labelCol"
:wrapper-col="wrapperCol"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 18 }"
>
<Tabs v-model:activeKey="tabActivedKey" @change="handleChangeTab">
<!-- Api 资源基本信息 -->
@ -59,13 +59,13 @@
</span>
<template #overlay>
<Menu @click="handleClickMenu">
<MenuItem key="properties">{{ L('Propertites') }}</MenuItem>
<MenuItem key="Properties">{{ L('Propertites') }}</MenuItem>
</Menu>
</template>
</Dropdown>
</template>
<component
:is="advancedComponent"
:is="componentsRef[advancedComponent]"
:properties="modelRef.properties"
@props-new="handleNewProperty"
@props-delete="handleDeleteProperty"
@ -76,8 +76,9 @@
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
<script lang="ts" setup>
import { ref, unref, shallowRef } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { DownOutlined } from '@ant-design/icons-vue';
import { Checkbox, Dropdown, Menu, Tabs, Form } from 'ant-design-vue';
@ -88,86 +89,57 @@
import { useProperty } from '../hooks/useProperty';
import UserClaim from '../../components/UserClaim.vue';
import Properties from '../../components/Properties.vue';
export default defineComponent({
name: 'IdentityResourceModal',
components: {
UserClaim,
Properties,
BasicModal,
DownOutlined,
Form,
FormItem: Form.Item,
Dropdown,
Menu,
MenuItem: Menu.Item,
Tabs,
TabPane: Tabs.TabPane,
Input,
Checkbox,
},
emits: ['change', 'register'],
setup(_, { emit }) {
const { L } = useLocalization('AbpIdentityServer');
const formElRef = ref<any>(null);
const modelIdRef = ref('');
const tabActivedKey = ref('basic');
const advancedComponent = ref('properties');
const [registerModal, { changeOkLoading }] = useModalInner((val) => {
modelIdRef.value = val.id;
});
const {
isEdit,
modelRef,
formRules,
formTitle,
handleChangeTab,
handleVisibleModal,
handleSubmit,
} = useModal({
modelIdRef,
formElRef,
tabActivedKey,
});
const { handleNewProperty, handleDeleteProperty } = useProperty({ modelRef });
const { targetClaims, handleClaimChange } = useClaim({ modelRef });
function handleClickMenu(e) {
tabActivedKey.value = 'advanced';
advancedComponent.value = e.key;
}
const FormItem = Form.Item;
const MenuItem = Menu.Item;
const TabPane = Tabs.TabPane;
function handleOk() {
changeOkLoading(true);
handleSubmit()
.then(() => {
emit('change');
})
.finally(() => {
changeOkLoading(false);
});
}
const emits = defineEmits(['change', 'register']);
return {
L,
isEdit,
formElRef,
formRules,
formTitle,
tabActivedKey,
registerModal,
modelRef,
advancedComponent,
labelCol: { span: 6 },
wrapperCol: { span: 18 },
handleClickMenu,
handleNewProperty,
handleDeleteProperty,
handleChangeTab,
handleVisibleModal,
handleOk,
targetClaims,
handleClaimChange,
};
},
const componentsRef = shallowRef({
'Properties': Properties,
});
const { createMessage } = useMessage();
const { L } = useLocalization('AbpIdentityServer');
const formElRef = ref<any>(null);
const modelIdRef = ref('');
const tabActivedKey = ref('basic');
const advancedComponent = ref('Properties');
const [registerModal, { changeOkLoading }] = useModalInner((val) => {
modelIdRef.value = val.id;
});
const {
isEdit,
modelRef,
formRules,
formTitle,
handleChangeTab,
handleVisibleModal,
handleSubmit,
} = useModal({
modelIdRef,
formElRef,
tabActivedKey,
});
const { handleNewProperty, handleDeleteProperty } = useProperty({ modelRef });
const { targetClaims, handleClaimChange } = useClaim({ modelRef });
function handleClickMenu(e) {
tabActivedKey.value = 'advanced';
advancedComponent.value = e.key;
}
function handleOk() {
const formEl = unref(formElRef);
formEl?.validate().then(() => {
changeOkLoading(true);
handleSubmit().then(() => {
createMessage.success(L('Successful'));
emits('change');
}).finally(() => {
changeOkLoading(false);
});
});
}
</script>

128
apps/vue/src/views/identity-server/identity-resources/components/IdentityResourceTable.vue

@ -6,16 +6,20 @@
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'enabled'">
<Switch :checked="record.enabled" readonly />
<CheckOutlined v-if="record.enabled" class="enable" />
<CloseOutlined v-else class="disable" />
</template>
<template v-else-if="column.key === 'required'">
<Switch :checked="record.required" readonly />
<CheckOutlined v-if="record.required" class="enable" />
<CloseOutlined v-else class="disable" />
</template>
<template v-else-if="column.key === 'emphasize'">
<Switch :checked="record.emphasize" readonly />
<CheckOutlined v-if="record.emphasize" class="enable" />
<CloseOutlined v-else class="disable" />
</template>
<template v-else-if="column.key === 'showInDiscoveryDocument'">
<Switch :checked="record.showInDiscoveryDocument" readonly />
<CheckOutlined v-if="record.showInDiscoveryDocument" class="enable" />
<CloseOutlined v-else class="disable" />
</template>
<template v-else-if="column.key === 'actions'">
<TableAction
@ -42,9 +46,10 @@
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { Button, Modal, Switch } from 'ant-design-vue';
<script lang="ts" setup>
import { Button } from 'ant-design-vue';
import { CheckOutlined, CloseOutlined } from '@ant-design/icons-vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicTable, TableAction, useTable } from '/@/components/Table';
import { useModal } from '/@/components/Modal';
@ -54,70 +59,57 @@
import { formatPagedRequest } from '/@/utils/http/abp/helper';
import IdentityResourceModal from './IdentityResourceModal.vue';
export default defineComponent({
name: 'IdentityResourceTable',
components: { IdentityResourceModal, BasicTable, Button, Switch, TableAction },
setup() {
const { L } = useLocalization('AbpIdentityServer');
const [registerModal, { openModal, closeModal }] = useModal();
const [registerTable, { reload }] = useTable({
rowKey: 'id',
title: L('DisplayName:IdentityResources'),
columns: getDataColumns(),
api: getList,
beforeFetch: formatPagedRequest,
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: true,
immediate: true,
canColDrag: true,
formConfig: getSearchFormSchemas(),
actionColumn: {
width: 200,
title: L('Actions'),
dataIndex: 'actions',
},
});
const { createMessage, createConfirm } = useMessage();
const { L } = useLocalization('AbpIdentityServer');
const [registerModal, { openModal, closeModal }] = useModal();
const [registerTable, { reload }] = useTable({
rowKey: 'id',
title: L('DisplayName:IdentityResources'),
columns: getDataColumns(),
api: getList,
beforeFetch: formatPagedRequest,
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: true,
immediate: true,
canColDrag: true,
formConfig: getSearchFormSchemas(),
actionColumn: {
width: 200,
title: L('Actions'),
dataIndex: 'actions',
},
});
function handleAddNew() {
openModal(true, {});
}
function handleAddNew() {
openModal(true, {});
}
function handleEdit(record) {
openModal(true, record);
}
function handleEdit(record) {
openModal(true, record);
}
function handleChange() {
closeModal();
reload();
}
function handleChange() {
closeModal();
reload();
}
function handleDelete(record) {
Modal.warning({
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
reload();
});
},
function handleDelete(record) {
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reload();
});
}
return {
L,
registerModal,
registerTable,
handleAddNew,
handleDelete,
handleEdit,
handleChange,
};
},
});
},
});
}
</script>

28
apps/vue/src/views/identity-server/identity-resources/datas/TableData.ts

@ -11,6 +11,20 @@ export function getDataColumns(): BasicColumn[] {
width: 1,
ifShow: false,
},
{
title: L('Enabled'),
dataIndex: 'enabled',
align: 'center',
width: 150,
sorter: true,
},
{
title: L('Required'),
dataIndex: 'required',
align: 'center',
width: 150,
sorter: true,
},
{
title: L('Name'),
dataIndex: 'name',
@ -32,20 +46,6 @@ export function getDataColumns(): BasicColumn[] {
width: 180,
sorter: true,
},
{
title: L('Required'),
dataIndex: 'required',
align: 'center',
width: 200,
sorter: true,
},
{
title: L('Enabled'),
dataIndex: 'enabled',
align: 'center',
width: 200,
sorter: true,
},
{
title: L('Emphasize'),
dataIndex: 'emphasize',

32
apps/vue/src/views/identity-server/identity-resources/hooks/useModal.ts

@ -1,8 +1,8 @@
import type { Ref } from 'vue';
import { computed, ref, reactive, unref, watch } from 'vue';
import { message } from 'ant-design-vue';
import { cloneDeep } from 'lodash-es';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useValidation } from '/@/hooks/abp/useValidation';
@ -16,6 +16,7 @@ interface UseModal {
}
export function useModal({ modelIdRef, formElRef, tabActivedKey }: UseModal) {
const { createMessage } = useMessage();
const { L } = useLocalization('AbpIdentityServer');
const { ruleCreator } = useValidation();
const modelRef = ref<IdentityResource>({} as IdentityResource);
@ -69,25 +70,20 @@ export function useModal({ modelIdRef, formElRef, tabActivedKey }: UseModal) {
function handleSubmit() {
return new Promise<any>((resolve, reject) => {
const formEl = unref(formElRef);
formEl
.validate()
.then(() => {
const input = cloneDeep(unref(modelRef));
const api = isEdit.value
? update(input.id, Object.assign(input))
: create(Object.assign(input));
api
.then((res) => {
message.success(L('Successful'));
resolve(res);
})
.catch((error) => {
reject(error);
});
})
.catch((error) => {
formEl.validate().then(() => {
const input = cloneDeep(unref(modelRef));
const api = isEdit.value
? update(input.id, Object.assign(input))
: create(Object.assign(input));
api.then((res) => {
createMessage.success(L('Successful'));
resolve(res);
}).catch((error) => {
reject(error);
});
}).catch((error) => {
reject(error);
});
});
}

20
apps/vue/src/views/identity-server/persisted-grants/components/ModalData.ts

@ -1,4 +1,4 @@
import { h } from 'vue';
import { createVNode } from 'vue';
import { Input } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { JsonPreview } from '/@/components/CodeEditor';
@ -35,7 +35,7 @@ export function getModalFormSchemas(): FormSchema[] {
label: L('Grants:Key'),
colProps: { span: 24 },
render: ({ model, field }) => {
return h(Input, {
return createVNode(Input, {
value: model[field],
readonly: true,
placeholder: '',
@ -48,7 +48,7 @@ export function getModalFormSchemas(): FormSchema[] {
label: L('Grants:Type'),
colProps: { span: 24 },
render: ({ model, field }) => {
return h(Input, {
return createVNode(Input, {
value: model[field],
readonly: true,
placeholder: '',
@ -61,7 +61,7 @@ export function getModalFormSchemas(): FormSchema[] {
label: L('Grants:SubjectId'),
colProps: { span: 24 },
render: ({ model, field }) => {
return h(Input, {
return createVNode(Input, {
value: model[field],
readonly: true,
placeholder: '',
@ -74,7 +74,7 @@ export function getModalFormSchemas(): FormSchema[] {
label: L('Grants:SessionId'),
colProps: { span: 24 },
render: ({ model, field }) => {
return h(Input, {
return createVNode(Input, {
value: model[field],
readonly: true,
placeholder: '',
@ -87,7 +87,7 @@ export function getModalFormSchemas(): FormSchema[] {
label: L('Description'),
colProps: { span: 24 },
render: ({ model, field }) => {
return h(Input, {
return createVNode(Input, {
value: model[field],
readonly: true,
placeholder: '',
@ -100,7 +100,7 @@ export function getModalFormSchemas(): FormSchema[] {
label: L('CreationTime'),
colProps: { span: 24 },
render: ({ model, field }) => {
return h(Input, {
return createVNode(Input, {
value: model[field]
? formatToDateTime(model[field], 'YYYY-MM-DD HH:mm:ss')
: model[field],
@ -115,7 +115,7 @@ export function getModalFormSchemas(): FormSchema[] {
label: L('Expiration'),
colProps: { span: 24 },
render: ({ model, field }) => {
return h(Input, {
return createVNode(Input, {
value: model[field]
? formatToDateTime(model[field], 'YYYY-MM-DD HH:mm:ss')
: model[field],
@ -130,7 +130,7 @@ export function getModalFormSchemas(): FormSchema[] {
label: L('Grants:ConsumedTime'),
colProps: { span: 24 },
render: ({ model, field }) => {
return h(Input, {
return createVNode(Input, {
value: model[field]
? formatToDateTime(model[field], 'YYYY-MM-DD HH:mm:ss')
: model[field],
@ -145,7 +145,7 @@ export function getModalFormSchemas(): FormSchema[] {
label: L('Grants:Data'),
colProps: { span: 24 },
render: ({ model, field }) => {
return h(JsonPreview, {
return createVNode(JsonPreview!, {
data: model[field] ? JSON.parse(model[field]) : {},
});
},

72
apps/vue/src/views/identity-server/persisted-grants/components/PersistedGrantModal.vue

@ -6,60 +6,42 @@
:width="660"
:min-height="400"
>
<BasicForm
ref="formElRef"
:model="persistedGrantRef"
:colon="true"
:schemas="formSchemas"
:label-width="120"
:show-action-button-group="false"
:action-col-options="{
span: 24,
}"
/>
<BasicForm @register="registerForm" />
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, ref, watch, unref } from 'vue';
<script lang="ts" setup>
import { nextTick } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicForm, FormActionType } from '/@/components/Form';
import { BasicForm, useForm } from '/@/components/Form';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { getModalFormSchemas } from './ModalData';
import { get } from '/@/api/identity-server/persistedGrants';
import { PersistedGrant } from '/@/api/identity-server/model/persistedGrantsModel';
export default defineComponent({
name: 'PersistedGrantModal',
components: { BasicForm, BasicModal },
emits: ['register'],
setup() {
const { L } = useLocalization('AbpIdentityServer');
const persistedGrantIdRef = ref('');
const persistedGrantRef = ref<PersistedGrant | null>(null);
const formElRef = ref<Nullable<FormActionType>>(null);
const [registerModal] = useModalInner((val) => {
persistedGrantIdRef.value = val.id;
});
const formSchemas = getModalFormSchemas();
watch(
() => unref(persistedGrantIdRef),
(id) => {
const formEl = unref(formElRef);
formEl?.resetFields();
get(id).then((res) => {
persistedGrantRef.value = res;
});
},
);
defineEmits(['register']);
return {
L,
formElRef,
formSchemas,
registerModal,
persistedGrantRef,
};
const { L } = useLocalization('AbpIdentityServer');
const [registerForm, { resetFields, setFieldsValue }] = useForm({
colon: true,
labelWidth: 120,
showActionButtonGroup: false,
actionColOptions: {
span: 24,
},
schemas: getModalFormSchemas(),
});
const [registerModal] = useModalInner((val) => {
nextTick(() => {
fetchPersistedGrant(val.id);
});
});
function fetchPersistedGrant(id?: string) {
resetFields();
if (id) {
get(id).then((res) => {
setFieldsValue(res);
});
}
}
</script>

98
apps/vue/src/views/identity-server/persisted-grants/components/PersistedGrantTable.vue

@ -27,9 +27,8 @@
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { Modal } from 'ant-design-vue';
<script lang="ts" setup>
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicTable, TableAction, useTable } from '/@/components/Table';
import { useModal } from '/@/components/Modal';
@ -39,59 +38,48 @@
import { formatPagedRequest } from '/@/utils/http/abp/helper';
import PersistedGrantModal from './PersistedGrantModal.vue';
export default defineComponent({
name: 'PersistedGrantTable',
components: { BasicTable, TableAction, PersistedGrantModal },
setup() {
const { L } = useLocalization('AbpIdentityServer');
const [registerModal, { openModal }] = useModal();
const [registerTable, { reload }] = useTable({
rowKey: 'id',
title: L('DisplayName:PersistedGrants'),
columns: getDataColumns(),
api: getList,
beforeFetch: formatPagedRequest,
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: true,
immediate: true,
canColDrag: true,
formConfig: getSearchFormSchemas(),
actionColumn: {
width: 160,
title: L('Actions'),
dataIndex: 'actions',
},
});
const { createMessage, createConfirm } = useMessage();
const { L } = useLocalization('AbpIdentityServer');
const [registerModal, { openModal }] = useModal();
const [registerTable, { reload }] = useTable({
rowKey: 'id',
title: L('DisplayName:PersistedGrants'),
columns: getDataColumns(),
api: getList,
beforeFetch: formatPagedRequest,
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: true,
immediate: true,
canColDrag: true,
formConfig: getSearchFormSchemas(),
actionColumn: {
width: 160,
title: L('Actions'),
dataIndex: 'actions',
},
});
function handleShow(record) {
openModal(true, record);
}
function handleShow(record) {
openModal(true, record);
}
function handleDelete(record) {
Modal.warning({
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
reload();
});
},
function handleDelete(record) {
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reload();
});
}
return {
L,
registerModal,
registerTable,
handleDelete,
handleShow,
};
},
});
},
});
}
</script>

66
apps/vue/src/views/identity/claim-types/components/ClaimModal.vue

@ -21,48 +21,40 @@
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, ref, unref } from 'vue';
<script lang="ts" setup>
import { ref, unref } from 'vue';
import { BasicForm, FormActionType } from '/@/components/Form';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { useClaimModal } from '../hooks/useClaimModal';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { IdentityClaimType } from '/@/api/identity/model/claimModel';
export default defineComponent({
name: 'ClaimModal',
components: { BasicForm, BasicModal },
emits: ['change', 'register'],
setup(_props, { emit }) {
const submiting = ref(false);
const claimRef = ref<Nullable<IdentityClaimType>>(null);
const formElRef = ref<Nullable<FormActionType>>(null);
const [registerModal, { closeModal }] = useModalInner((val) => {
claimRef.value = val;
});
const { formTitle, formSchemas, handleSubmit } = useClaimModal({ claimRef, formElRef });
function handleSaveChanges() {
const formEl = unref(formElRef);
formEl?.validate().then(() => {
submiting.value = true;
handleSubmit(formEl.getFieldsValue())
.then(() => {
emit('change');
closeModal();
})
.finally(() => {
submiting.value = false;
});
});
}
const emits = defineEmits(['change', 'register']);
return {
submiting,
formElRef,
formTitle,
formSchemas,
registerModal,
handleSaveChanges,
};
},
const { createMessage } = useMessage();
const { L } = useLocalization('AbpIdentity');
const submiting = ref(false);
const claimRef = ref<Nullable<IdentityClaimType>>(null);
const formElRef = ref<Nullable<FormActionType>>(null);
const [registerModal, { closeModal }] = useModalInner((val) => {
claimRef.value = val;
});
const { formTitle, formSchemas, handleSubmit } = useClaimModal({ claimRef, formElRef });
function handleSaveChanges() {
const formEl = unref(formElRef);
formEl?.validate().then(() => {
submiting.value = true;
handleSubmit(formEl.getFieldsValue())
.then(() => {
createMessage.success(L('Successful'));
emits('change');
closeModal();
})
.finally(() => {
submiting.value = false;
});
});
}
</script>

48
apps/vue/src/views/identity/claim-types/components/ClaimTable.vue

@ -49,8 +49,7 @@
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
<script lang="ts" setup>
import { CheckOutlined, CloseOutlined } from '@ant-design/icons-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { usePermission } from '/@/hooks/web/usePermission';
@ -59,39 +58,16 @@
import { useClaimTable } from '../hooks/useClaimTable';
import ClaimModal from './ClaimModal.vue';
export default defineComponent({
name: 'ClaimTable',
components: {
BasicTable,
ClaimModal,
CheckOutlined,
CloseOutlined,
TableAction,
},
setup() {
const { L } = useLocalization('AbpIdentity');
const { hasPermission } = usePermission();
const [registerModal, { openModal }] = useModal();
const { valueTypeMap, registerTable, reloadTable, handleDelete } = useClaimTable();
const { L } = useLocalization('AbpIdentity');
const { hasPermission } = usePermission();
const [registerModal, { openModal }] = useModal();
const { valueTypeMap, registerTable, reloadTable, handleDelete } = useClaimTable();
return {
L,
hasPermission,
valueTypeMap,
registerTable,
reloadTable,
registerModal,
openModal,
handleDelete,
};
},
methods: {
handleAddNew() {
this.openModal(true, {}, true);
},
handleEdit(record) {
this.openModal(true, record, true);
},
},
});
function handleAddNew() {
openModal(true, {});
}
function handleEdit(record) {
openModal(true, record);
}
</script>

9
apps/vue/src/views/identity/claim-types/hooks/useClaimTable.ts

@ -1,14 +1,15 @@
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useMessage } from '/@/hooks/web/useMessage';
import { useTable } from '/@/components/Table';
import { deleteById, getList } from '/@/api/identity/claim';
import { ValueType } from '/@/api/identity/model/claimModel';
import { formatPagedRequest } from '/@/utils/http/abp/helper';
import { getDataColumns } from '../datas/TableData';
import { getSearchFormSchemas } from '../datas/ModalData';
import { Modal } from 'ant-design-vue';
export function useClaimTable() {
const { L } = useLocalization('AbpIdentity');
const { createMessage, createConfirm } = useMessage();
const valueTypeMap = {
[ValueType.String]: 'String',
[ValueType.Int]: 'Int',
@ -39,12 +40,14 @@ export function useClaimTable() {
});
function handleDelete(role) {
Modal.warning({
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessageWithFormat', [role.name] as Recordable),
content: L('ItemWillBeDeletedMessageWithFormat', [role.name]),
okCancel: true,
onOk: () => {
deleteById(role.id).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reloadTable();
});
},

2
apps/vue/src/views/identity/components/ClaimModal.vue

@ -151,7 +151,7 @@
onOk: () => {
if (isFunction(props.deleteApi)) {
props.deleteApi(identityRef.value, claim).then(() => {
createMessage.success(L('Successful'));
createMessage.success(L('SuccessfullyDeleted'));
reload();
});
}

209
apps/vue/src/views/identity/components/MenuModal.vue

@ -41,8 +41,8 @@
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, ref, unref, watch } from 'vue';
<script lang="ts" setup>
import { ref, unref, watch } from 'vue';
import { Card, Form, Select, TreeSelect } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicModal, useModalInner } from '/@/components/Modal';
@ -51,128 +51,103 @@
import { MenuListResult } from '/@/api/platform/model/menuModel';
import { getAll } from '/@/api/platform/menu';
import { listToTree } from '/@/utils/helper/treeHelper';
export default defineComponent({
name: 'MenuModal',
components: {
BasicModal,
BasicTree,
Card,
Form,
FormItem: Form.Item,
Select,
TreeSelect,
const FormItem = Form.Item;
const emits = defineEmits(['change', 'change:startup', 'register']);
const props = defineProps({
loading: {
type: Boolean,
default: false,
},
props: {
loading: {
type: Boolean,
default: false,
},
getMenuApi: {
type: Function as PropType<(...args) => Promise<MenuListResult>>,
required: true,
default: new Promise<MenuListResult>((resolve) => {
return resolve({
items: [],
});
}),
},
getMenuApi: {
type: Function as PropType<(...args) => Promise<MenuListResult>>,
required: true,
default: new Promise<MenuListResult>((resolve) => {
return resolve({
items: [],
});
}),
},
emits: ['change', 'register', 'change:startup'],
setup(props, { emit }) {
const { L } = useLocalization('AppPlatform');
const identityRef = ref('');
const frameworkRef = ref('');
const startupMenuRef = ref('');
const menuTreeRef = ref<any[]>([]);
const defaultCheckedRef = ref<any[]>([]);
const checkedRef = ref<string[]>([]);
const replaceFields = {
key: 'id',
title: 'displayName',
children: 'children',
value: 'id',
};
const optionsRef = ref<
{
key: string;
label: string;
value: string;
}[]
>([]);
const [registerModal, { changeOkLoading }] = useModalInner((record) => {
identityRef.value = record.identity;
optionsRef.value = [];
frameworkRef.value = '';
startupMenuRef.value = '';
checkedRef.value = [];
defaultCheckedRef.value = [];
menuTreeRef.value = [];
});
});
watch(
() => unref(props).loading,
(busy) => {
changeOkLoading(busy);
},
);
const { L } = useLocalization('AppPlatform');
const identityRef = ref('');
const frameworkRef = ref('');
const startupMenuRef = ref('');
const menuTreeRef = ref<any[]>([]);
const defaultCheckedRef = ref<any[]>([]);
const checkedRef = ref<string[]>([]);
const replaceFields = {
key: 'id',
title: 'displayName',
children: 'children',
value: 'id',
};
const optionsRef = ref<
{
key: string;
label: string;
value: string;
}[]
>([]);
const [registerModal, { changeOkLoading }] = useModalInner((record) => {
identityRef.value = record.identity;
optionsRef.value = [];
frameworkRef.value = '';
startupMenuRef.value = '';
checkedRef.value = [];
defaultCheckedRef.value = [];
menuTreeRef.value = [];
});
function handleSelect(value) {
getAll({
filter: '',
sorting: '',
framework: value,
}).then((res) => {
menuTreeRef.value = listToTree(res.items, { id: 'id', pid: 'parentId' });
});
props.getMenuApi(unref(identityRef), value).then((res) => {
checkedRef.value = res.items.map((item) => item.id);
defaultCheckedRef.value = checkedRef.value;
const startupMenu = res.items.find((item) => item.startup);
if (startupMenu) {
startupMenuRef.value = startupMenu.id;
}
});
}
watch(
() => unref(props).loading,
(busy) => {
changeOkLoading(busy);
},
);
function handleVisibleChange(visible) {
if (visible) {
getByName('UI Framework').then((res) => {
optionsRef.value = res.items.map((item) => {
return {
key: item.id,
label: item.displayName,
value: item.name,
};
});
});
}
function handleSelect(value) {
getAll({
filter: '',
sorting: '',
framework: value,
}).then((res) => {
menuTreeRef.value = listToTree(res.items, { id: 'id', pid: 'parentId' });
});
props.getMenuApi(unref(identityRef), value).then((res) => {
checkedRef.value = res.items.map((item) => item.id);
defaultCheckedRef.value = checkedRef.value;
const startupMenu = res.items.find((item) => item.startup);
if (startupMenu) {
startupMenuRef.value = startupMenu.id;
}
});
}
function handleCheck(checkedKeys) {
checkedRef.value = checkedKeys.checked;
}
function handleVisibleChange(visible) {
if (visible) {
getByName('UI Framework').then((res) => {
optionsRef.value = res.items.map((item) => {
return {
key: item.id,
label: item.displayName,
value: item.name,
};
});
});
}
}
function handleSubmit() {
emit('change', unref(identityRef), unref(checkedRef));
if (unref(startupMenuRef)) {
emit('change:startup', unref(identityRef), unref(startupMenuRef));
}
}
function handleCheck(checkedKeys) {
checkedRef.value = checkedKeys.checked;
}
return {
L,
menuTreeRef,
defaultCheckedRef,
replaceFields,
frameworkRef,
startupMenuRef,
optionsRef,
registerModal,
handleSelect,
handleVisibleChange,
handleCheck,
handleSubmit,
};
},
});
function handleSubmit() {
emits('change', unref(identityRef), unref(checkedRef));
if (unref(startupMenuRef)) {
emits('change:startup', unref(identityRef), unref(startupMenuRef));
}
}
</script>

188
apps/vue/src/views/identity/organization-units/components/MemberModal.vue

@ -18,8 +18,9 @@
</BasicModal>
</template>
<script lang="ts">
import { computed, defineComponent, ref, unref } from 'vue';
<script lang="ts" setup>
import { computed, ref, unref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { Input } from 'ant-design-vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
@ -27,106 +28,93 @@
import { formatPagedRequest } from '/@/utils/http/abp/helper';
import { addMembers, getUnaddedMemberList } from '/@/api/identity/organization-units';
export default defineComponent({
name: 'MemberModal',
components: { BasicModal, BasicTable, InputSearch: Input.Search },
props: {
ouId: { type: String },
},
emits: ['change', 'register'],
setup(props, { emit }) {
const { L } = useLocalization('AbpIdentity');
const loading = ref(false);
const filter = ref('');
const tableRef = ref<Nullable<TableActionType>>(null);
const [registerModal, { closeModal }] = useModalInner();
const dataColumns: BasicColumn[] = [
{
title: 'id',
dataIndex: 'id',
width: 1,
ifShow: false,
},
{
title: L('DisplayName:UserName'),
dataIndex: 'userName',
align: 'left',
width: 280,
sorter: true,
},
{
title: L('EmailAddress'),
dataIndex: 'email',
align: 'left',
width: 'auto',
sorter: true,
},
];
const requestApi = computed(() => {
return (request) => {
request.id = unref(props).ouId;
request.filter = unref(filter);
formatPagedRequest(request);
};
});
const [registerTable] = useTable({
rowKey: 'id',
columns: dataColumns,
api: getUnaddedMemberList,
beforeFetch: requestApi,
pagination: true,
striped: false,
useSearchForm: false,
showTableSetting: false,
bordered: true,
showIndexColumn: false,
canResize: false,
immediate: true,
rowSelection: { type: 'checkbox' },
});
const InputSearch = Input.Search;
function handleSearch() {
const tableEl = unref(tableRef);
tableEl?.reload();
tableEl?.clearSelectedRowKeys();
}
const emits = defineEmits(['change', 'register']);
const props = defineProps({
ouId: { type: String },
});
const { createMessage } = useMessage();
const { L } = useLocalization('AbpIdentity');
const loading = ref(false);
const filter = ref('');
const tableRef = ref<Nullable<TableActionType>>(null);
const [registerModal, { closeModal }] = useModalInner();
const dataColumns: BasicColumn[] = [
{
title: 'id',
dataIndex: 'id',
width: 1,
ifShow: false,
},
{
title: L('DisplayName:UserName'),
dataIndex: 'userName',
align: 'left',
width: 280,
sorter: true,
},
{
title: L('EmailAddress'),
dataIndex: 'email',
align: 'left',
width: 'auto',
sorter: true,
},
];
const requestApi = computed(() => {
return (request) => {
request.id = unref(props).ouId;
request.filter = unref(filter);
formatPagedRequest(request);
};
});
const [registerTable] = useTable({
rowKey: 'id',
columns: dataColumns,
api: getUnaddedMemberList,
beforeFetch: requestApi,
pagination: true,
striped: false,
useSearchForm: false,
showTableSetting: false,
bordered: true,
showIndexColumn: false,
canResize: false,
immediate: true,
rowSelection: { type: 'checkbox' },
});
function handleVisibleChange(visible) {
if (visible) {
handleSearch();
}
}
function handleSearch() {
const tableEl = unref(tableRef);
tableEl?.reload();
tableEl?.clearSelectedRowKeys();
}
function handleSubmit() {
const tableEl = unref(tableRef);
const selectRows = tableEl?.getSelectRows();
if (selectRows) {
loading.value = true;
addMembers(
props.ouId!,
selectRows.map((x) => x.id),
)
.then(() => {
emit('change');
closeModal();
})
.finally(() => {
loading.value = false;
});
}
}
function handleVisibleChange(visible) {
if (visible) {
handleSearch();
}
}
return {
L,
filter,
loading,
tableRef,
registerModal,
registerTable,
handleVisibleChange,
handleSearch,
handleSubmit,
};
},
});
function handleSubmit() {
const tableEl = unref(tableRef);
const selectRows = tableEl?.getSelectRows();
if (selectRows) {
loading.value = true;
addMembers(
props.ouId!,
selectRows.map((x) => x.id),
)
.then(() => {
createMessage.success(L('Successful'));
emits('change');
closeModal();
})
.finally(() => {
loading.value = false;
});
}
}
</script>

63
apps/vue/src/views/identity/organization-units/components/MemberTable.vue

@ -30,8 +30,8 @@
<MemberModal @register="registerModal" :ou-id="ouId" @change="handleChange" />
</template>
<script lang="ts">
import { computed, defineComponent, unref } from 'vue';
<script lang="ts" setup>
import { computed, unref } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { usePermission } from '/@/hooks/web/usePermission';
import { BasicTable, TableAction } from '/@/components/Table';
@ -40,44 +40,29 @@
import { useModal } from '/@/components/Modal';
import MemberModal from './MemberModal.vue';
export default defineComponent({
name: 'MemberTable',
components: { BasicTable, MemberModal, TableAction },
props: {
ouId: { type: String },
},
setup(props) {
const { L } = useLocalization('AbpIdentity');
const { hasPermission } = usePermission();
const getProps = computed(() => {
return { ...props } as MemberProps;
});
const addMemberEnabled = computed(() => {
if (!unref(getProps).ouId) {
return false;
}
return hasPermission('AbpIdentity.OrganizationUnits.ManageUsers');
});
const { registerTable, reloadMembers, handleDelete } = useMemberTable({ getProps });
const [registerModal, { openModal }] = useModal();
const props = defineProps({
ouId: { type: String },
});
function handleAddNew() {
openModal();
}
const { L } = useLocalization('AbpIdentity');
const { hasPermission } = usePermission();
const getProps = computed(() => {
return { ...props } as MemberProps;
});
const addMemberEnabled = computed(() => {
if (!unref(getProps).ouId) {
return false;
}
return hasPermission('AbpIdentity.OrganizationUnits.ManageUsers');
});
const { registerTable, reloadMembers, handleDelete } = useMemberTable({ getProps });
const [registerModal, { openModal }] = useModal();
function handleChange() {
reloadMembers();
}
function handleAddNew() {
openModal();
}
return {
L,
addMemberEnabled,
registerTable,
handleChange,
handleDelete,
registerModal,
handleAddNew,
};
},
});
function handleChange() {
reloadMembers();
}
</script>

38
apps/vue/src/views/identity/organization-units/components/OrganizationUnitPage.vue

@ -18,41 +18,21 @@
</Row>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
<script lang="ts" setup>
import { ref } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { Card, Row, Col, Tabs } from 'ant-design-vue';
import OrganizationUnitTree from './OrganizationUnitTree.vue';
import MemberTable from './MemberTable.vue';
import RoleTable from './RoleTable.vue';
export default defineComponent({
name: 'OrganizationUnitPage',
components: {
OrganizationUnitTree,
Card,
Col,
MemberTable,
Row,
RoleTable,
Tabs,
TabPane: Tabs.TabPane,
},
setup() {
const { L } = useLocalization('AbpIdentity');
const activeKey = ref('members');
const ouIdRef = ref('');
const TabPane = Tabs.TabPane;
function handleSelect(key) {
ouIdRef.value = key;
}
const { L } = useLocalization('AbpIdentity');
const activeKey = ref('members');
const ouIdRef = ref('');
return {
L,
activeKey,
ouIdRef,
handleSelect,
};
},
});
function handleSelect(key) {
ouIdRef.value = key;
}
</script>

47
apps/vue/src/views/identity/organization-units/components/OrganizationUnitTree.vue

@ -29,8 +29,7 @@
</Card>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
<script lang="ts" setup>
import { Card } from 'ant-design-vue';
import { usePermission } from '/@/hooks/web/usePermission';
import { useLocalization } from '/@/hooks/abp/useLocalization';
@ -40,36 +39,18 @@
import { PermissionModal } from '/@/components/Permission';
import OrganizationUnitModal from './OrganizationUnitModal.vue';
export default defineComponent({
name: 'OrganizationUnitTree',
components: { BasicTree, Card, OrganizationUnitModal, PermissionModal },
emits: ['change', 'select'],
setup(_props, { emit }) {
const { L } = useLocalization('AbpIdentity');
const [registerModal, modalMethods] = useModal();
const [registerPermissionModal, permissionModalMethods] = useModal();
const {
ouTree,
getContentMenus,
handleDrop,
handleAddNew,
handleSelect,
loadOuTree,
} = useOuTree({ emit, modalMethods, permissionModalMethods });
const { hasPermission } = usePermission();
const emits = defineEmits(['change', 'select']);
return {
L,
ouTree,
loadOuTree,
registerModal,
getContentMenus,
hasPermission,
handleDrop,
handleAddNew,
handleSelect,
registerPermissionModal,
};
},
});
const { L } = useLocalization('AbpIdentity');
const [registerModal, modalMethods] = useModal();
const [registerPermissionModal, permissionModalMethods] = useModal();
const {
ouTree,
getContentMenus,
handleDrop,
handleAddNew,
handleSelect,
loadOuTree,
} = useOuTree({ emit: emits, modalMethods, permissionModalMethods });
const { hasPermission } = usePermission();
</script>

174
apps/vue/src/views/identity/organization-units/components/RoleModal.vue

@ -18,8 +18,9 @@
</BasicModal>
</template>
<script lang="ts">
import { computed, defineComponent, ref, unref } from 'vue';
<script lang="ts" setup>
import { computed, ref, unref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { Input } from 'ant-design-vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
@ -27,99 +28,86 @@
import { formatPagedRequest } from '/@/utils/http/abp/helper';
import { addRoles, getUnaddedRoleList } from '/@/api/identity/organization-units';
export default defineComponent({
name: 'RoleModal',
components: { BasicModal, BasicTable, InputSearch: Input.Search },
props: {
ouId: { type: String },
},
emits: ['change', 'register'],
setup(props, { emit }) {
const { L } = useLocalization('AbpIdentity');
const loading = ref(false);
const filter = ref('');
const tableRef = ref<Nullable<TableActionType>>(null);
const [registerModal, { closeModal }] = useModalInner();
const dataColumns: BasicColumn[] = [
{
title: 'id',
dataIndex: 'id',
width: 1,
ifShow: false,
},
{
title: L('RoleName'),
dataIndex: 'name',
align: 'left',
width: 'auto',
sorter: true,
},
];
const requestApi = computed(() => {
return (request) => {
request.id = unref(props).ouId;
request.filter = unref(filter);
formatPagedRequest(request);
};
});
const [registerTable] = useTable({
rowKey: 'id',
columns: dataColumns,
api: getUnaddedRoleList,
beforeFetch: requestApi,
pagination: true,
striped: false,
useSearchForm: false,
showTableSetting: false,
bordered: true,
showIndexColumn: false,
canResize: false,
immediate: true,
rowSelection: { type: 'checkbox' },
});
function handleSearch() {
const tableEl = unref(tableRef);
tableEl?.reload();
tableEl?.clearSelectedRowKeys();
}
function handleVisibleChange(visible) {
if (visible) {
handleSearch();
}
}
const InputSearch = Input.Search;
function handleSubmit() {
const tableEl = unref(tableRef);
const selectRows = tableEl?.getSelectRows();
if (selectRows) {
loading.value = true;
addRoles(
props.ouId!,
selectRows.map((x) => x.id),
)
.then(() => {
emit('change');
closeModal();
})
.finally(() => {
loading.value = false;
});
}
}
const emits = defineEmits(['change', 'register']);
const props = defineProps({
ouId: { type: String },
});
return {
L,
filter,
loading,
tableRef,
registerModal,
registerTable,
handleVisibleChange,
handleSearch,
handleSubmit,
};
const { createMessage } = useMessage();
const { L } = useLocalization('AbpIdentity');
const loading = ref(false);
const filter = ref('');
const tableRef = ref<Nullable<TableActionType>>(null);
const [registerModal, { closeModal }] = useModalInner();
const dataColumns: BasicColumn[] = [
{
title: 'id',
dataIndex: 'id',
width: 1,
ifShow: false,
},
{
title: L('RoleName'),
dataIndex: 'name',
align: 'left',
width: 'auto',
sorter: true,
},
];
const requestApi = computed(() => {
return (request) => {
request.id = unref(props).ouId;
request.filter = unref(filter);
formatPagedRequest(request);
};
});
const [registerTable] = useTable({
rowKey: 'id',
columns: dataColumns,
api: getUnaddedRoleList,
beforeFetch: requestApi,
pagination: true,
striped: false,
useSearchForm: false,
showTableSetting: false,
bordered: true,
showIndexColumn: false,
canResize: false,
immediate: true,
rowSelection: { type: 'checkbox' },
});
function handleSearch() {
const tableEl = unref(tableRef);
tableEl?.reload();
tableEl?.clearSelectedRowKeys();
}
function handleVisibleChange(visible) {
if (visible) {
handleSearch();
}
}
function handleSubmit() {
const tableEl = unref(tableRef);
const selectRows = tableEl?.getSelectRows();
if (selectRows) {
loading.value = true;
addRoles(
props.ouId!,
selectRows.map((x) => x.id),
)
.then(() => {
createMessage.success(L('Successful'));
emits('change');
closeModal();
})
.finally(() => {
loading.value = false;
});
}
}
</script>

63
apps/vue/src/views/identity/organization-units/components/RoleTable.vue

@ -30,8 +30,8 @@
<RoleModal @register="registerModal" :ou-id="ouId" @change="handleChange" />
</template>
<script lang="ts">
import { computed, defineComponent, unref } from 'vue';
<script lang="ts" setup>
import { computed, unref } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { usePermission } from '/@/hooks/web/usePermission';
import { BasicTable, TableAction } from '/@/components/Table';
@ -40,44 +40,29 @@
import { useModal } from '/@/components/Modal';
import RoleModal from './RoleModal.vue';
export default defineComponent({
name: 'RoleTable',
components: { BasicTable, RoleModal, TableAction },
props: {
ouId: { type: String },
},
setup(props) {
const { L } = useLocalization('AbpIdentity');
const { hasPermission } = usePermission();
const getProps = computed(() => {
return { ...props } as MemberProps;
});
const addRoleEnabled = computed(() => {
if (!unref(getProps).ouId) {
return false;
}
return hasPermission('AbpIdentity.OrganizationUnits.ManageRoles');
});
const { registerTable, reloadRoles, handleDelete } = useRoleTable({ getProps });
const [registerModal, { openModal }] = useModal();
const props = defineProps({
ouId: { type: String },
});
function handleAddNew() {
openModal();
}
const { L } = useLocalization('AbpIdentity');
const { hasPermission } = usePermission();
const getProps = computed(() => {
return { ...props } as MemberProps;
});
const addRoleEnabled = computed(() => {
if (!unref(getProps).ouId) {
return false;
}
return hasPermission('AbpIdentity.OrganizationUnits.ManageRoles');
});
const { registerTable, reloadRoles, handleDelete } = useRoleTable({ getProps });
const [registerModal, { openModal }] = useModal();
function handleChange() {
reloadRoles();
}
function handleAddNew() {
openModal();
}
return {
L,
addRoleEnabled,
registerTable,
registerModal,
handleDelete,
handleAddNew,
handleChange,
};
},
});
function handleChange() {
reloadRoles();
}
</script>

14
apps/vue/src/views/identity/organization-units/hooks/useMemberTable.ts

@ -1,6 +1,6 @@
import { ComputedRef } from 'vue';
import { Modal } from 'ant-design-vue';
import type { ComputedRef } from 'vue';
import { watch, ref, unref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicColumn, useTable } from '/@/components/Table';
import { User } from '/@/api/identity/model/userModel';
@ -14,6 +14,7 @@ interface UseMemberTable {
export function useMemberTable({ getProps }: UseMemberTable) {
const { L } = useLocalization('AbpIdentity');
const { createMessage, createConfirm } = useMessage();
const dataSource = ref([] as User[]);
const dataColumns: BasicColumn[] = [
{
@ -61,12 +62,17 @@ export function useMemberTable({ getProps }: UseMemberTable) {
});
function handleDelete(user) {
Modal.warning({
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('OrganizationUnit:AreYouSureRemoveUser', [user.userName] as Recordable),
okCancel: true,
onOk: () => {
removeOrganizationUnit(user.id, unref(getProps).ouId).then(() => reloadMembers());
removeOrganizationUnit(user.id, unref(getProps).ouId)
.then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reloadMembers();
});
},
});
}

6
apps/vue/src/views/identity/organization-units/hooks/useOuTree.ts

@ -1,5 +1,4 @@
import { computed, onMounted, ref } from 'vue';
import { Modal } from 'ant-design-vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { usePermission } from '/@/hooks/web/usePermission';
import { useLocalization } from '/@/hooks/abp/useLocalization';
@ -13,7 +12,7 @@ export function useOuTree({ emit, modalMethods, permissionModalMethods }:
modalMethods: ReturnMethods,
permissionModalMethods: ReturnMethods,
}) {
const { createMessage } = useMessage();
const { createMessage, createConfirm } = useMessage();
const { L } = useLocalization(['AbpIdentity']);
const { hasPermission } = usePermission();
const ouTree = ref<any[]>([]);
@ -38,7 +37,8 @@ export function useOuTree({ emit, modalMethods, permissionModalMethods }:
{
label: L('Delete'),
handler: () => {
Modal.warning({
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,

12
apps/vue/src/views/identity/organization-units/hooks/useRoleTable.ts

@ -1,7 +1,7 @@
import { ComputedRef } from 'vue';
import { Modal } from 'ant-design-vue';
import { ref, unref, watch } from 'vue';
import { useTable } from '/@/components/Table';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { getDataColumns } from '../../role/datas/TableData';
import { Role } from '/@/api/identity/model/roleModel';
@ -15,6 +15,7 @@ interface UseRoleTable {
export function useRoleTable({ getProps }: UseRoleTable) {
const { L } = useLocalization('AbpIdentity');
const { createMessage, createConfirm } = useMessage();
const dataSource = ref([] as Role[]);
const [registerTable] = useTable({
rowKey: 'id',
@ -40,12 +41,17 @@ export function useRoleTable({ getProps }: UseRoleTable) {
});
function handleDelete(role) {
Modal.warning({
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('OrganizationUnit:AreYouSureRemoveRole', [role.name] as Recordable),
okCancel: true,
onOk: () => {
removeOrganizationUnit(role.id, unref(getProps).ouId).then(() => reloadRoles());
removeOrganizationUnit(role.id, unref(getProps).ouId)
.then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reloadRoles();
});
},
});
}

1
apps/vue/src/views/identity/organization-units/index.vue

@ -7,6 +7,7 @@
import OrganizationUnitPage from './components/OrganizationUnitPage.vue';
export default defineComponent({
name: 'OrganizationUnits',
components: { OrganizationUnitPage },
});
</script>

61
apps/vue/src/views/identity/role/components/ClaimModal.vue

@ -42,50 +42,33 @@
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
<script lang="ts" setup>
import { ref } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicTable, TableAction } from '/@/components/Table';
import { BasicModalForm } from '/@/components/ModalForm';
import { useClaim } from '../hooks/useClaim';
export default defineComponent({
name: 'RoleClaimModal',
components: { BasicModal, BasicTable, BasicModalForm, TableAction },
setup() {
const { L } = useLocalization('AbpIdentity');
const roleIdRef = ref('');
const [registerModal] = useModalInner((val) => {
roleIdRef.value = val.id;
});
const {
formSchemas,
registerClaimForm,
openClaimForm,
registerTable,
handleDelete,
handleSaveChanges,
} = useClaim({ roleIdRef });
return {
L,
formSchemas,
registerModal,
registerTable,
registerClaimForm,
openClaimForm,
handleDelete,
handleSaveChanges,
};
},
methods: {
handleAddNew() {
this.openClaimForm({});
},
handleEdit(record) {
this.openClaimForm(record);
},
},
const { L } = useLocalization('AbpIdentity');
const roleIdRef = ref('');
const [registerModal] = useModalInner((val) => {
roleIdRef.value = val.id;
});
const {
formSchemas,
registerClaimForm,
openClaimForm,
registerTable,
handleDelete,
handleSaveChanges,
} = useClaim({ roleIdRef });
function handleAddNew() {
openClaimForm({});
}
function handleEdit(record) {
openClaimForm(record);
}
</script>

68
apps/vue/src/views/identity/role/components/RoleModal.vue

@ -19,48 +19,40 @@
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, ref, unref } from 'vue';
<script lang="ts" setup>
import { ref, unref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicForm, FormActionType } from '/@/components/Form';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { useRoleModal } from '../hooks/useRoleModal';
import { Role } from '/@/api/identity/model/roleModel';
export default defineComponent({
name: '',
components: { BasicForm, BasicModal },
emits: ['change', 'register'],
setup(_props, { emit }) {
const submiting = ref(false);
const roleRef = ref<Nullable<Role>>(null);
const formElRef = ref<Nullable<FormActionType>>(null);
const [registerModal, { closeModal }] = useModalInner((val) => {
roleRef.value = val;
});
const { formTitle, formSchemas, handleSubmit } = useRoleModal({ roleRef, formElRef });
function handleSaveChanges() {
const formEl = unref(formElRef);
formEl?.validate().then(() => {
submiting.value = true;
handleSubmit(formEl.getFieldsValue())
.then(() => {
emit('change');
closeModal();
})
.finally(() => {
submiting.value = false;
});
});
}
return {
submiting,
formElRef,
formTitle,
formSchemas,
registerModal,
handleSaveChanges,
};
},
const emits = defineEmits(['change', 'register']);
const submiting = ref(false);
const roleRef = ref<Nullable<Role>>(null);
const formElRef = ref<Nullable<FormActionType>>(null);
const { createMessage } = useMessage();
const { L } = useLocalization('AbpIdentity');
const [registerModal, { closeModal }] = useModalInner((val) => {
roleRef.value = val;
});
const { formTitle, formSchemas, handleSubmit } = useRoleModal({ roleRef, formElRef });
function handleSaveChanges() {
const formEl = unref(formElRef);
formEl?.validate().then(() => {
submiting.value = true;
handleSubmit(formEl.getFieldsValue())
.then(() => {
createMessage.success(L('Successful'));
emits('change');
closeModal();
})
.finally(() => {
submiting.value = false;
});
});
}
</script>

115
apps/vue/src/views/identity/role/components/RoleTable.vue

@ -75,8 +75,8 @@
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
<script lang="ts" setup>
import { ref } from 'vue';
import { Tag } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { usePermission } from '/@/hooks/web/usePermission';
@ -91,86 +91,45 @@
import MenuModal from '../../components/MenuModal.vue';
import ClaimModal from '../../components/ClaimModal.vue';
export default defineComponent({
name: 'RoleTable',
components: {
BasicTable,
ClaimModal,
MenuModal,
RoleModal,
Tag,
TableAction,
PermissionModal,
},
setup() {
const { L } = useLocalization(['AbpIdentity', 'AppPlatform']);
const loadMenuRef = ref(false);
const { hasPermission } = usePermission();
const [registerModal, { openModal }] = useModal();
const [registerClaimModal, { openModal: openClaimModal }] = useModal();
const [registerMenuModal, { openModal: openMenuModal, closeModal: closeMenuModal }] =
useModal();
const { registerTable, reloadTable, handleDelete } = useRoleTable();
const { registerModel: registerPermissionModal, showPermissionModal } = usePermissionModal();
const { L } = useLocalization(['AbpIdentity', 'AppPlatform']);
const loadMenuRef = ref(false);
const { hasPermission } = usePermission();
const [registerModal, { openModal }] = useModal();
const [registerClaimModal, { openModal: openClaimModal }] = useModal();
const [registerMenuModal, { openModal: openMenuModal, closeModal: closeMenuModal }] =
useModal();
const { registerTable, reloadTable, handleDelete } = useRoleTable();
const { registerModel: registerPermissionModal, showPermissionModal } = usePermissionModal();
function handleSetMenu(record) {
openMenuModal(true, { identity: record.name }, true);
}
function handleSetMenu(record) {
openMenuModal(true, { identity: record.name }, true);
}
function handleChangeMenu(roleName, menuIds) {
loadMenuRef.value = true;
setRoleMenu({
roleName: roleName,
menuIds: menuIds,
})
.then(() => {
closeMenuModal();
})
.finally(() => {
loadMenuRef.value = false;
});
}
function handleChangeMenu(roleName, menuIds) {
loadMenuRef.value = true;
setRoleMenu({
roleName: roleName,
menuIds: menuIds,
}).then(() => {
closeMenuModal();
}).finally(() => {
loadMenuRef.value = false;
});
}
function handleChangeStartupMenu(roleName, meunId) {
setRoleStartupMenu(roleName, meunId);
}
function handleChangeStartupMenu(roleName, meunId) {
setRoleStartupMenu(roleName, meunId);
}
function handleAddNew() {
openModal(true, {}, true);
}
function handleAddNew() {
openModal(true, {}, true);
}
function handleEdit(record) {
openModal(true, record, true);
}
function handleEdit(record) {
openModal(true, record, true);
}
function handleShowClaims(record) {
openClaimModal(true, { id: record.id });
}
return {
L,
loadMenuRef,
hasPermission,
registerTable,
reloadTable,
registerModal,
registerClaimModal,
handleShowClaims,
registerPermissionModal,
showPermissionModal,
registerMenuModal,
handleAddNew,
handleEdit,
handleSetMenu,
handleDelete,
handleChangeMenu,
handleChangeStartupMenu,
getListByRole,
getRoleClaims,
createClaim,
updateClaim,
deleteClaim,
};
},
});
function handleShowClaims(record) {
openClaimModal(true, { id: record.id });
}
</script>

15
apps/vue/src/views/identity/role/hooks/useClaim.ts

@ -1,7 +1,6 @@
import type { Ref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { Modal } from 'ant-design-vue';
import { FormSchema } from '/@/components/Form';
import { useModal } from '/@/components/Modal';
import { getActivedList } from '/@/api/identity/claim';
@ -16,6 +15,7 @@ interface UseClaim {
// TODO: 与UserClaim重复 需要分离组件
export function useClaim({ roleIdRef }: UseClaim) {
const { L } = useLocalization('AbpIdentity');
const { createMessage, createConfirm } = useMessage();
const formSchemas: FormSchema[] = [
{
field: 'id',
@ -102,14 +102,17 @@ export function useClaim({ roleIdRef }: UseClaim) {
}
function handleDelete(claim) {
Modal.warning({
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessageWithFormat', [claim.claimValue] as Recordable),
okCancel: true,
onOk: () => {
deleteClaim(unref(roleIdRef), claim).then(() => {
reloadTable();
});
deleteClaim(unref(roleIdRef), claim)
.then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reloadTable();
});
},
});
}

7
apps/vue/src/views/identity/role/hooks/useRoleTable.ts

@ -1,13 +1,14 @@
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useMessage } from '/@/hooks/web/useMessage';
import { useTable } from '/@/components/Table';
import { deleteById, getList } from '/@/api/identity/role';
import { formatPagedRequest } from '/@/utils/http/abp/helper';
import { getDataColumns } from '../datas/TableData';
import { getSearchFormSchemas } from '../datas/ModalData';
import { Modal } from 'ant-design-vue';
export function useRoleTable() {
const { L } = useLocalization('AbpIdentity');
const { createMessage, createConfirm } = useMessage();
const [registerTable, { reload: reloadTable }] = useTable({
rowKey: 'id',
title: L('Roles'),
@ -32,12 +33,14 @@ export function useRoleTable() {
});
function handleDelete(role) {
Modal.warning({
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessageWithFormat', [role.name] as Recordable),
okCancel: true,
onOk: () => {
deleteById(role.id).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reloadTable();
});
},

90
apps/vue/src/views/identity/security-logs/components/SecurityLogTable.vue

@ -18,9 +18,8 @@
</BasicTable>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { Modal } from 'ant-design-vue';
<script lang="ts" setup>
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicTable, TableAction, useTable } from '/@/components/Table';
import { getDataColumns } from './TableData';
@ -28,53 +27,44 @@
import { deleteById, getList } from '/@/api/identity/securityLog';
import { formatPagedRequest } from '/@/utils/http/abp/helper';
export default defineComponent({
name: 'SecurityLogTable',
components: { BasicTable, TableAction },
setup() {
const { L } = useLocalization('AbpAuditLogging');
const [registerTable, { reload }] = useTable({
rowKey: 'id',
title: L('SecurityLog'),
columns: getDataColumns(),
api: getList,
beforeFetch: formatPagedRequest,
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: true,
immediate: true,
canColDrag: true,
formConfig: getSearchFormSchemas(),
scroll: { x: 'max-content', y: '100%' },
actionColumn: {
width: 120,
title: L('Actions'),
dataIndex: 'actions',
},
});
function handleDelete(record) {
Modal.warning({
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
reload();
});
},
});
}
return {
L,
registerTable,
handleDelete,
};
const { createMessage, createConfirm } = useMessage();
const { L } = useLocalization('AbpAuditLogging');
const [registerTable, { reload }] = useTable({
rowKey: 'id',
title: L('SecurityLog'),
columns: getDataColumns(),
api: getList,
beforeFetch: formatPagedRequest,
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: true,
immediate: true,
canColDrag: true,
formConfig: getSearchFormSchemas(),
scroll: { x: 'max-content', y: '100%' },
actionColumn: {
width: 120,
title: L('Actions'),
dataIndex: 'actions',
},
});
function handleDelete(record) {
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reload();
});
},
});
}
</script>

45
apps/vue/src/views/identity/user/components/LockModal.vue

@ -7,39 +7,30 @@
/>
</template>
<script lang="ts">
import { defineComponent, ref, unref } from 'vue';
<script lang="ts" setup>
import { ref, unref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicModalForm } from '/@/components/ModalForm';
import { useModalInner } from '/@/components/Modal';
import { useLock } from '../hooks/useLock';
export default defineComponent({
name: 'LockModal',
components: { BasicModalForm },
emits: ['change', 'register'],
setup(_props, { emit }) {
const { L } = useLocalization('AbpIdentity');
const userIdRef = ref('');
const { formSchemas, handleLock } = useLock({ emit });
const [registerModal, { closeModal }] = useModalInner((val) => {
userIdRef.value = val.userId;
});
function handleSaveChanges(input) {
return handleLock(unref(userIdRef), input).then(() => {
closeModal();
});
}
const emits = defineEmits(['change', 'register']);
return {
L,
formSchemas,
handleLock,
handleSaveChanges,
registerModal,
};
},
const { L } = useLocalization('AbpIdentity');
const { createMessage } = useMessage();
const userIdRef = ref('');
const { formSchemas, handleLock } = useLock({ emit: emits });
const [registerModal, { closeModal }] = useModalInner((val) => {
userIdRef.value = val.userId;
});
function handleSaveChanges(input) {
return handleLock(unref(userIdRef), input)
.then(() => {
createMessage.success(L('Successful'));
closeModal();
});
}
</script>

75
apps/vue/src/views/identity/user/components/PasswordModal.vue

@ -9,57 +9,42 @@
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, ref, unref } from 'vue';
<script lang="ts" setup>
import { ref, unref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm, FormActionType } from '/@/components/Form';
import { usePassword } from '../hooks/usePassword';
import { changePassword } from '/@/api/identity/user';
export default defineComponent({
name: 'PasswordModal',
components: { BasicModal, BasicForm },
setup() {
const { L } = useLocalization('AbpIdentity');
const userIdRef = ref('');
const formElRef = ref<Nullable<FormActionType>>(null);
const { formSchemas } = usePassword(formElRef);
const [registerModal, { closeModal }] = useModalInner((val) => {
userIdRef.value = val;
});
const [registerForm, { getFieldsValue, validate }] = useForm({
schemas: formSchemas,
showActionButtonGroup: false,
actionColOptions: {
span: 24,
},
});
function handleSubmit() {
const userId = unref(userIdRef);
if (userId) {
validate().then((res) => {
changePassword(userId, {
password: res.password,
}).then(() => {
closeModal();
});
});
}
}
return {
L,
formElRef,
registerModal,
closeModal,
registerForm,
getFieldsValue,
validate,
userIdRef,
handleSubmit,
};
const { createMessage } = useMessage();
const { L } = useLocalization('AbpIdentity');
const userIdRef = ref('');
const formElRef = ref<Nullable<FormActionType>>(null);
const { formSchemas } = usePassword(formElRef);
const [registerModal, { closeModal }] = useModalInner((val) => {
userIdRef.value = val;
});
const [registerForm, { validate }] = useForm({
schemas: formSchemas,
showActionButtonGroup: false,
actionColOptions: {
span: 24,
},
});
function handleSubmit() {
const userId = unref(userIdRef);
if (userId) {
validate().then((res) => {
changePassword(userId, {
password: res.password,
}).then(() => {
createMessage.success(L('Successful'));
closeModal();
});
});
}
}
</script>

91
apps/vue/src/views/identity/user/components/UserModal.vue

@ -62,72 +62,49 @@
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
<script lang="ts" setup>
import { ref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { message, Checkbox, Input, Form, Tabs, Transfer } from 'ant-design-vue';
import { Checkbox, Input, Form, Tabs, Transfer } from 'ant-design-vue';
import { Input as BInput } from '/@/components/Input';
import { FormActionType } from '/@/components/Form';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { useUserForm } from '../hooks/useUserForm';
export default defineComponent({
name: 'UserModal',
components: {
BasicModal,
Checkbox,
Form,
FormItem: Form.Item,
Tabs,
TabPane: Tabs.TabPane,
BInput,
InputPassword: Input.Password,
Transfer,
},
emits: ['register', 'change'],
setup(_, { emit }) {
const { L } = useLocalization(['AbpIdentity', 'AbpIdentityServer']);
const activedTab = ref('info');
const userRef = ref<Recordable>({});
const formElRef = ref<Nullable<FormActionType>>(null);
const { handleSubmit, getUser, userTitle, formRules, roleDataSource, handleRoleChange } =
useUserForm({
userRef,
formElRef,
});
const [registerModal, { closeModal, changeOkLoading }] = useModalInner(async (val) => {
activedTab.value = 'info';
getUser(val.id);
});
const FormItem = Form.Item;
const TabPane = Tabs.TabPane;
const InputPassword = Input.Password;
function handleOk() {
changeOkLoading(true);
handleSubmit()
.then((res) => {
message.success(L('Successful'));
closeModal();
emit('change', res);
})
.finally(() => {
changeOkLoading(false);
});
}
const emits = defineEmits(['register', 'change']);
return {
L,
activedTab,
userRef,
formElRef,
formRules,
roleDataSource,
handleRoleChange,
userTitle,
handleOk,
registerModal,
closeModal,
};
},
const { createMessage } = useMessage();
const { L } = useLocalization(['AbpIdentity', 'AbpIdentityServer']);
const activedTab = ref('info');
const userRef = ref<Recordable>({});
const formElRef = ref<Nullable<FormActionType>>(null);
const { handleSubmit, getUser, userTitle, formRules, roleDataSource, handleRoleChange } =
useUserForm({
userRef,
formElRef,
});
const [registerModal, { closeModal, changeOkLoading }] = useModalInner(async (val) => {
activedTab.value = 'info';
getUser(val.id);
});
function handleOk() {
changeOkLoading(true);
handleSubmit()
.then((res) => {
createMessage.success(L('Successful'));
closeModal();
emits('change', res);
})
.finally(() => {
changeOkLoading(false);
});
}
</script>
<style scoped>

141
apps/vue/src/views/identity/user/components/UserTable.vue

@ -106,8 +106,8 @@
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
<script lang="ts" setup>
import { ref } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { usePermission } from '/@/hooks/web/usePermission';
import { Tag } from 'ant-design-vue';
@ -126,105 +126,56 @@
import MenuModal from '../../components/MenuModal.vue';
import ClaimModal from '../../components/ClaimModal.vue';
export default defineComponent({
name: 'UserTable',
components: {
BasicTable,
ClaimModal,
PermissionModal,
TableAction,
Tag,
UserModal,
PasswordModal,
LockModal,
MenuModal,
},
setup(_props, { emit }) {
const { L } = useLocalization(['AbpIdentity', 'AppPlatform']);
const loadMenuRef = ref(false);
const nullFormElRef = ref(null);
const { hasPermission } = usePermission();
const [registerModal, { openModal }] = useModal();
const { lockEnable, registerTable, reloadTable, handleDelete } = useUserTable();
const { registerLockModal, showLockModal, handleUnLock } = useLock({ emit });
const { registerPasswordModal, showPasswordModal } = usePassword(nullFormElRef);
const [registerClaimModal, { openModal: openClaimModal }] = useModal();
const [registerMenuModal, { openModal: openMenuModal, closeModal: closeMenuModal }] =
useModal();
const { registerModel: registerPermissionModal, showPermissionModal } = usePermissionModal();
const emits = defineEmits(['change']);
function handleSetMenu(record) {
openMenuModal(true, { identity: record.id }, true);
}
const { L } = useLocalization(['AbpIdentity', 'AppPlatform']);
const loadMenuRef = ref(false);
const nullFormElRef = ref(null);
const { hasPermission } = usePermission();
const [registerModal, { openModal }] = useModal();
const { lockEnable, registerTable, reloadTable, handleDelete } = useUserTable();
const { registerLockModal, showLockModal, handleUnLock } = useLock({ emit: emits });
const { registerPasswordModal, showPasswordModal } = usePassword(nullFormElRef);
const [registerClaimModal, { openModal: openClaimModal }] = useModal();
const [registerMenuModal, { openModal: openMenuModal, closeModal: closeMenuModal }] =
useModal();
const { registerModel: registerPermissionModal, showPermissionModal } = usePermissionModal();
function handleChangeMenu(userId, menuIds) {
loadMenuRef.value = true;
setUserMenu({
userId: userId,
menuIds: menuIds,
})
.then(() => {
closeMenuModal();
})
.finally(() => {
loadMenuRef.value = false;
});
}
function handleSetMenu(record) {
openMenuModal(true, { identity: record.id }, true);
}
function handleAddNew() {
openModal(true, {}, true);
}
function handleChangeMenu(userId, menuIds) {
loadMenuRef.value = true;
setUserMenu({
userId: userId,
menuIds: menuIds,
}) .then(() => {
closeMenuModal();
}) .finally(() => {
loadMenuRef.value = false;
});
}
function handleEdit(record) {
openModal(true, record, true);
}
function handleAddNew() {
openModal(true, {}, true);
}
function handleUnlock(record) {
handleUnLock(record.id).then(() => {
reloadTable();
});
}
function handleEdit(record) {
openModal(true, record, true);
}
function handleChangeStartupMenu(userId, meunId) {
setUserStartupMenu(userId, meunId);
}
function handleUnlock(record) {
handleUnLock(record.id).then(() => {
reloadTable();
});
}
function handleShowClaims(record) {
openClaimModal(true, { id: record.id });
}
function handleChangeStartupMenu(userId, meunId) {
setUserStartupMenu(userId, meunId);
}
return {
L,
loadMenuRef,
hasPermission,
lockEnable,
registerTable,
reloadTable,
registerModal,
openModal,
registerPermissionModal,
showPermissionModal,
registerPasswordModal,
showPasswordModal,
registerClaimModal,
handleShowClaims,
handleDelete,
registerLockModal,
showLockModal,
handleUnLock,
registerMenuModal,
handleAddNew,
handleEdit,
handleUnlock,
handleSetMenu,
handleChangeMenu,
handleChangeStartupMenu,
getListByUser,
getUserClaims,
createClaim,
updateClaim,
deleteClaim,
};
},
});
function handleShowClaims(record) {
openClaimModal(true, { id: record.id });
}
</script>

14
apps/vue/src/views/identity/user/hooks/useUserForm.ts

@ -106,14 +106,12 @@ export function useUserForm({ userRef, formElRef }: UseUserFormContext) {
const api = user.id
? update(user.id, cloneDeep(user) as UpdateUser)
: create(cloneDeep(user) as CreateUser);
api
.then((res) => {
userRef.value = {};
resolve(res);
})
.catch((error) => {
reject(error);
});
api.then((res) => {
userRef.value = {};
resolve(res);
}).catch((error) => {
reject(error);
});
})
.catch((error) => {
reject(error);

14
apps/vue/src/views/identity/user/hooks/useUserTable.ts

@ -1,13 +1,14 @@
import { computed } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useTable } from '/@/components/Table';
import { deleteById, getList } from '/@/api/identity/user';
import { formatPagedRequest } from '/@/utils/http/abp/helper';
import { getDataColumns } from '../datas/TableData';
import { getSearchFormSchemas } from '../datas/ModalData';
import { Modal } from 'ant-design-vue';
export function useUserTable() {
const { createMessage, createConfirm } = useMessage();
const { L } = useLocalization('AbpIdentity');
const [registerTable, { reload: reloadTable }] = useTable({
rowKey: 'id',
@ -51,14 +52,17 @@ export function useUserTable() {
});
function handleDelete(user) {
Modal.warning({
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessageWithFormat', [user.userName] as Recordable),
okCancel: true,
onOk: () => {
deleteById(user.id).then(() => {
reloadTable();
});
deleteById(user.id)
.then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reloadTable();
});
},
});
}

97
apps/vue/src/views/localization/languages/components/LanguageTable.vue

@ -4,73 +4,50 @@
</div>
</template>
<script lang="ts">
import { defineComponent, onMounted } from 'vue';
import { Switch } from 'ant-design-vue';
<script lang="ts" setup>
import { onMounted } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { usePermission } from '/@/hooks/web/usePermission';
import { BasicTable, useTable } from '/@/components/Table';
import { formatPagedRequest } from '/@/utils/http/abp/helper';
import { getList } from '/@/api/localization/languages';
import { getDataColumns } from './TableData';
export default defineComponent({
name: 'LanguageTable',
components: {
BasicTable,
Switch,
},
setup() {
const { L } = useLocalization(['AbpLocalization', 'AbpUi']);
const { hasPermission } = usePermission();
const [registerTable, { setTableData, getForm }] = useTable({
rowKey: 'cultureName',
title: L('Languages'),
columns: getDataColumns(),
beforeFetch: formatPagedRequest,
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: false,
immediate: false,
formConfig: {
labelWidth: 100,
schemas: [
{
field: 'filter',
component: 'Input',
label: L('Search'),
colProps: { span: 24 },
defaultValue: '',
},
],
submitFunc: fetchLanguages,
const { L } = useLocalization(['AbpLocalization', 'AbpUi']);
const [registerTable, { setTableData, getForm }] = useTable({
rowKey: 'cultureName',
title: L('Languages'),
columns: getDataColumns(),
beforeFetch: formatPagedRequest,
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: false,
immediate: false,
formConfig: {
labelWidth: 100,
schemas: [
{
field: 'filter',
component: 'Input',
label: L('Search'),
colProps: { span: 24 },
defaultValue: '',
},
});
onMounted(fetchLanguages);
function fetchLanguages() {
const form = getForm();
return form.validate().then(() => {
return getList().then((res) => {
setTableData(res.items);
});
});
}
function handleChange() {
fetchLanguages();
}
return {
L,
hasPermission,
registerTable,
handleChange,
};
],
submitFunc: fetchLanguages,
},
});
onMounted(fetchLanguages);
function fetchLanguages() {
const form = getForm();
return form.validate().then(() => {
return getList().then((res) => {
setTableData(res.items);
});
});
}
</script>

95
apps/vue/src/views/localization/resources/components/ResourceTable.vue

@ -4,71 +4,48 @@
</div>
</template>
<script lang="ts">
import { defineComponent, onMounted } from 'vue';
import { Switch } from 'ant-design-vue';
<script lang="ts" setup>
import { onMounted } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { usePermission } from '/@/hooks/web/usePermission';
import { BasicTable, useTable } from '/@/components/Table';
import { getList } from '/@/api/localization/resources';
import { getDataColumns } from './TableData';
export default defineComponent({
name: 'ResourceTable',
components: {
BasicTable,
Switch,
},
setup() {
const { L } = useLocalization(['LocalizationManagement', 'AbpUi']);
const { hasPermission } = usePermission();
const [registerTable, { setTableData, getForm }] = useTable({
rowKey: 'name',
title: L('Resources'),
columns: getDataColumns(),
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: false,
immediate: false,
formConfig: {
labelWidth: 100,
schemas: [
{
field: 'filter',
component: 'Input',
label: L('Search'),
colProps: { span: 24 },
defaultValue: '',
},
],
submitFunc: fetchResources,
const { L } = useLocalization(['LocalizationManagement', 'AbpUi']);
const [registerTable, { setTableData, getForm }] = useTable({
rowKey: 'name',
title: L('Resources'),
columns: getDataColumns(),
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: false,
immediate: false,
formConfig: {
labelWidth: 100,
schemas: [
{
field: 'filter',
component: 'Input',
label: L('Search'),
colProps: { span: 24 },
defaultValue: '',
},
});
onMounted(fetchResources);
function fetchResources() {
const form = getForm();
return form.validate().then(() => {
return getList().then((res) => {
setTableData(res.items);
});
});
}
function handleChange() {
fetchResources();
}
return {
L,
hasPermission,
registerTable,
handleChange,
};
],
submitFunc: fetchResources,
},
});
onMounted(fetchResources);
function fetchResources() {
const form = getForm();
return form.validate().then(() => {
return getList().then((res) => {
setTableData(res.items);
});
});
}
</script>

261
apps/vue/src/views/localization/texts/components/TextModal.vue

@ -11,155 +11,142 @@
</BasicModal>
</template>
<script lang="ts">
import { computed, defineComponent, ref, unref, nextTick } from 'vue';
<script lang="ts" setup>
import { computed, ref, unref, nextTick } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { message } from 'ant-design-vue';
import { BasicForm, FormSchema, FormActionType, useForm } from '/@/components/Form';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { Text } from '/@/api/localization/model/textsModel';
import { getByCulture, setText } from '/@/api/localization/texts';
import { getList as getLanguages } from '/@/api/localization/languages';
import { getList as getResources } from '/@/api/localization/resources';
export default defineComponent({
name: 'TextModal',
components: { BasicForm, BasicModal },
emits: ['change', 'register'],
setup(_props, { emit }) {
const { L } = useLocalization(['LocalizationManagement', 'AbpUi']);
const modelRef = ref<Nullable<Text>>(null);
const formElRef = ref<Nullable<FormActionType>>(null);
const formSchemas: FormSchema[] = [
{
field: 'id',
component: 'Input',
label: 'id',
colProps: { span: 24 },
show: false,
},
{
field: 'cultureName',
component: 'ApiSelect',
label: L('DisplayName:TargetCultureName'),
colProps: { span: 24 },
required: true,
componentProps: {
api: () => getLanguages(),
resultField: 'items',
labelField: 'uiCultureName',
valueField: 'cultureName',
onChange: (key) => {
//
const model = unref(modelRef);
if (model?.key) {
getByCulture({
const emits = defineEmits(['change', 'register']);
const { createMessage } = useMessage();
const { L } = useLocalization(['LocalizationManagement', 'AbpUi']);
const modelRef = ref<Nullable<Text>>(null);
const formElRef = ref<Nullable<FormActionType>>(null);
const formSchemas: FormSchema[] = [
{
field: 'id',
component: 'Input',
label: 'id',
colProps: { span: 24 },
show: false,
},
{
field: 'cultureName',
component: 'ApiSelect',
label: L('DisplayName:TargetCultureName'),
colProps: { span: 24 },
required: true,
componentProps: {
api: () => getLanguages(),
resultField: 'items',
labelField: 'uiCultureName',
valueField: 'cultureName',
onChange: (key) => {
//
const model = unref(modelRef);
if (model?.key) {
getByCulture({
key: model!.key,
cultureName: key,
resourceName: model!.resourceName,
}).then((res) => {
if (res) {
modelRef.value = res;
} else {
modelRef.value = {
value: '',
key: model!.key,
cultureName: key,
resourceName: model!.resourceName,
}).then((res) => {
if (res) {
modelRef.value = res;
} else {
modelRef.value = {
value: '',
key: model!.key,
cultureName: key,
resourceName: model!.resourceName,
};
}
const formEl = unref(formElRef);
formEl?.setFieldsValue(modelRef.value);
});
};
}
},
},
},
{
field: 'resourceName',
component: 'ApiSelect',
label: L('DisplayName:ResourceName'),
colProps: { span: 24 },
required: true,
componentProps: {
api: () => getResources(),
resultField: 'items',
labelField: 'displayName',
valueField: 'name',
},
dynamicDisabled: ({ values }) => {
return values.id ? true : false;
},
},
{
field: 'key',
component: 'Input',
label: L('DisplayName:Key'),
colProps: { span: 24 },
required: true,
dynamicDisabled: ({ values }) => {
return values.id ? true : false;
},
const formEl = unref(formElRef);
formEl?.setFieldsValue(modelRef.value);
});
}
},
{
field: 'value',
component: 'InputTextArea',
label: L('DisplayName:Value'),
colProps: { span: 24 },
required: true,
componentProps: {
rows: 5,
showCount: true,
},
},
];
const [registerForm, { resetFields, setFieldsValue }] = useForm({
colon: true,
labelWidth: 120,
schemas: formSchemas,
showActionButtonGroup: false,
actionColOptions: {
span: 24,
},
});
const [registerModal, { closeModal, changeOkLoading }] = useModalInner((val) => {
modelRef.value = val;
nextTick(() => {
resetFields();
setFieldsValue(val);
});
});
const formTitle = computed(() => {
const key = unref(modelRef)?.key;
if (key) {
return L('EditByName', [unref(modelRef)?.key] as Recordable);
}
return L('Text:AddNew');
});
function handleSubmit() {
const formEl = unref(formElRef);
formEl?.validate().then((input) => {
changeOkLoading(true);
setText(input).then(() => {
emit('change');
message.success(L('Successful'));
formEl?.resetFields();
closeModal();
})
.finally(() => {
changeOkLoading(false);
});
});
}
return {
L,
formElRef,
formTitle,
registerForm,
registerModal,
handleSubmit,
};
},
},
{
field: 'resourceName',
component: 'ApiSelect',
label: L('DisplayName:ResourceName'),
colProps: { span: 24 },
required: true,
componentProps: {
api: () => getResources(),
resultField: 'items',
labelField: 'displayName',
valueField: 'name',
},
dynamicDisabled: ({ values }) => {
return values.id ? true : false;
},
},
{
field: 'key',
component: 'Input',
label: L('DisplayName:Key'),
colProps: { span: 24 },
required: true,
dynamicDisabled: ({ values }) => {
return values.id ? true : false;
},
},
{
field: 'value',
component: 'InputTextArea',
label: L('DisplayName:Value'),
colProps: { span: 24 },
required: true,
componentProps: {
rows: 5,
showCount: true,
},
},
];
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
colon: true,
labelWidth: 120,
schemas: formSchemas,
showActionButtonGroup: false,
actionColOptions: {
span: 24,
},
});
const [registerModal, { closeModal, changeOkLoading }] = useModalInner((val) => {
modelRef.value = val;
nextTick(() => {
resetFields();
setFieldsValue(val);
});
});
const formTitle = computed(() => {
const key = unref(modelRef)?.key;
if (key) {
return L('EditByName', [unref(modelRef)?.key] as Recordable);
}
return L('Text:AddNew');
});
function handleSubmit() {
validate().then((input) => {
changeOkLoading(true);
setText(input).then(() => {
createMessage.success(L('Successful'));
emits('change');
resetFields();
closeModal();
})
.finally(() => {
changeOkLoading(false);
});
});
}
</script>

112
apps/vue/src/views/localization/texts/components/TextTable.vue

@ -29,10 +29,8 @@
</div>
</template>
<script lang="ts">
<script lang="ts" setup>
import { cloneDeep } from 'lodash-es';
import { defineComponent } from 'vue';
import { Switch } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { usePermission } from '/@/hooks/web/usePermission';
import { useModal } from '/@/components/Modal';
@ -42,74 +40,52 @@
import { getSearchFormSchemas } from './ModalData';
import TextModal from './TextModal.vue';
export default defineComponent({
name: 'TextTable',
components: {
BasicTable,
Switch,
TableAction,
TextModal,
const { L } = useLocalization(['LocalizationManagement', 'AbpUi']);
const { hasPermission } = usePermission();
const [registerModal, { openModal }] = useModal();
const [registerTable, { setTableData, setPagination, getForm }] = useTable({
rowKey: 'key',
title: L('Texts'),
columns: getDataColumns(),
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: false,
immediate: false,
formConfig: getSearchFormSchemas(fetchTexts),
actionColumn: {
width: 120,
title: L('Actions'),
dataIndex: 'action',
},
setup() {
const { L } = useLocalization(['LocalizationManagement', 'AbpUi']);
const { hasPermission } = usePermission();
const [registerModal, { openModal }] = useModal();
const [registerTable, { setTableData, setPagination, getForm }] = useTable({
rowKey: 'id',
title: L('Texts'),
columns: getDataColumns(),
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: false,
immediate: false,
formConfig: getSearchFormSchemas(fetchTexts),
actionColumn: {
width: 120,
title: L('Actions'),
dataIndex: 'action',
},
});
function fetchTexts() {
setPagination({
current: 1,
});
const form = getForm();
return form.validate().then((input) => {
const request = cloneDeep(input);
request.onlyNull = input.onlyNull === 1;
return getList(request).then((res) => {
return setTableData(res.items);
});
})
}
});
function handleChange() {
fetchTexts();
}
function fetchTexts() {
setPagination({
current: 1,
});
const form = getForm();
return form.validate().then((input) => {
const request = cloneDeep(input);
request.onlyNull = input.onlyNull === 1;
return getList(request).then((res) => {
return setTableData(res.items);
});
})
}
function handleAddNew() {
openModal(true, { id: null });
}
function handleChange() {
fetchTexts();
}
function handleEdit(record) {
openModal(true, {...{ id: 1 }, ...record});
}
function handleAddNew() {
openModal(true, { id: null });
}
return {
L,
hasPermission,
registerTable,
registerModal,
openModal,
handleChange,
handleAddNew,
handleEdit,
};
},
});
function handleEdit(record) {
openModal(true, {...{ id: 1 }, ...record});
}
</script>

156
apps/vue/src/views/oss-management/containers/components/ContainerTable.vue

@ -38,9 +38,8 @@
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { Modal, message } from 'ant-design-vue';
<script lang="ts" setup>
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { usePermission } from '/@/hooks/web/usePermission';
import { BasicModal, useModal } from '/@/components/Modal';
@ -51,95 +50,74 @@
import { getSearchFormSchemas, getModalFormSchemas } from './ModalData';
import { formatPagedRequest } from '/@/utils/http/abp/helper';
export default defineComponent({
name: 'ContainerTable',
components: {
BasicForm,
BasicModal,
BasicTable,
TableAction,
const { createMessage, createConfirm } = useMessage();
const { L } = useLocalization(['AbpOssManagement', 'AbpUi']);
const { hasPermission } = usePermission();
const [registerModal, { openModal, closeModal }] = useModal();
const [registerForm, { validate, resetFields }] = useForm({
labelWidth: 120,
schemas: getModalFormSchemas(),
showActionButtonGroup: false,
actionColOptions: {
span: 24,
},
setup() {
const { L } = useLocalization(['AbpOssManagement', 'AbpUi']);
const { hasPermission } = usePermission();
const [registerModal, { openModal, closeModal }] = useModal();
const [registerForm, { validate, resetFields }] = useForm({
labelWidth: 120,
schemas: getModalFormSchemas(),
showActionButtonGroup: false,
actionColOptions: {
span: 24,
},
});
const [registerTable, { reload }] = useTable({
rowKey: 'name',
title: L('Containers'),
columns: getDataColumns(),
api: getContainers,
fetchSetting: {
pageField: 'skipCount',
sizeField: 'maxResultCount',
listField: 'containers',
totalField: 'maxKeys',
},
beforeFetch: formatPagedRequest,
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: false,
immediate: true,
rowSelection: { type: 'checkbox' },
formConfig: getSearchFormSchemas(),
actionColumn: {
width: 120,
title: L('Actions'),
dataIndex: 'action',
},
});
function handleAddNew() {
resetFields();
openModal(true, {});
}
});
const [registerTable, { reload }] = useTable({
rowKey: 'name',
title: L('Containers'),
columns: getDataColumns(),
api: getContainers,
fetchSetting: {
pageField: 'skipCount',
sizeField: 'maxResultCount',
listField: 'containers',
totalField: 'maxKeys',
},
beforeFetch: formatPagedRequest,
pagination: true,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: false,
immediate: true,
rowSelection: { type: 'checkbox' },
formConfig: getSearchFormSchemas(),
actionColumn: {
width: 120,
title: L('Actions'),
dataIndex: 'action',
},
});
function handleDelete(record) {
Modal.warning({
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
deleteContainer(record.name).then(() => {
message.success(L('Successful'));
reload();
});
},
});
}
function handleAddNew() {
resetFields();
openModal(true, {});
}
function handleSubmit() {
validate().then((input) => {
createContainer(input.name).then(() => {
message.success(L('Successful'));
closeModal();
reload();
});
function handleDelete(record) {
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
deleteContainer(record.name).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reload();
});
}
},
});
}
return {
L,
hasPermission,
registerTable,
registerForm,
registerModal,
openModal,
handleAddNew,
handleDelete,
handleSubmit,
};
},
});
function handleSubmit() {
validate().then((input) => {
createContainer(input.name).then(() => {
createMessage.success(L('Successful'));
closeModal();
reload();
});
});
}
</script>

4
apps/vue/src/views/oss-management/objects/components/FileList.vue

@ -173,7 +173,7 @@
path: props.path,
objects: getSelectRowKeys(),
}).then(() => {
createMessage.success(L('Successful'));
createMessage.success(L('SuccessfullyDeleted'));
reload();
});
},
@ -199,7 +199,7 @@
path: props.path,
object: record.name,
}).then(() => {
createMessage.success(L('Successful'));
createMessage.success(L('SuccessfullyDeleted'));
reload();
});
},

81
apps/vue/src/views/oss-management/objects/components/OssFolderModal.vue

@ -10,59 +10,48 @@
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, ref, unref } from 'vue';
import { message } from 'ant-design-vue';
<script lang="ts" setup>
import { ref, unref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form';
import { getFolderModalSchemas } from '../datas/ModalData';
import { createObject } from '/@/api/oss-management/oss';
export default defineComponent({
name: 'OssFolderModal',
components: { BasicModal, BasicForm },
emits: ['register', 'change'],
setup(_, { emit }) {
const { L } = useLocalization(['AbpOssManagement', 'AbpUi']);
const bucket = ref('');
const path = ref('');
const [registerForm, { validate, resetFields }] = useForm({
labelWidth: 120,
schemas: getFolderModalSchemas(),
showActionButtonGroup: false,
actionColOptions: {
span: 24,
},
});
const [registerModal, { closeModal }] = useModalInner((data) => {
resetFields();
path.value = data.path;
bucket.value = data.bucket;
});
function handleSubmit() {
validate().then((input) => {
const name = input.name.endsWith('/') ? input.name : input.name + '/';
createObject({
bucket: unref(bucket),
path: unref(path),
object: name,
overwrite: false,
}).then(() => {
message.success(L('Successful'));
closeModal();
emit('change', name);
});
});
}
const emits = defineEmits(['register', 'change']);
return {
L,
registerForm,
registerModal,
handleSubmit,
};
const { createMessage } = useMessage();
const { L } = useLocalization(['AbpOssManagement', 'AbpUi']);
const bucket = ref('');
const path = ref('');
const [registerForm, { validate, resetFields }] = useForm({
labelWidth: 120,
schemas: getFolderModalSchemas(),
showActionButtonGroup: false,
actionColOptions: {
span: 24,
},
});
const [registerModal, { closeModal }] = useModalInner((data) => {
resetFields();
path.value = data.path;
bucket.value = data.bucket;
});
function handleSubmit() {
validate().then((input) => {
const name = input.name.endsWith('/') ? input.name : input.name + '/';
createObject({
bucket: unref(bucket),
path: unref(path),
object: name,
overwrite: false,
}).then(() => {
createMessage.success(L('Successful'));
closeModal();
emits('change', name);
});
});
}
</script>

75
apps/vue/src/views/oss-management/objects/components/OssManagePage.vue

@ -27,65 +27,42 @@
</div>
</template>
<script lang="ts">
import { defineComponent, ref, onMounted } from 'vue';
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
import { Card, Select } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { usePermission } from '/@/hooks/web/usePermission';
import { getContainers } from '/@/api/oss-management/oss';
import { OssContainer } from '/@/api/oss-management/model/ossModel';
import FolderTree from './FolderTree.vue';
import FileList from './FileList.vue';
export default defineComponent({
name: 'OssTable',
components: {
Card,
CardGrid: Card.Grid,
CardMeta: Card.Meta,
Select,
Option: Select.Option,
FolderTree,
FileList,
},
setup() {
const { L } = useLocalization(['AbpOssManagement', 'AbpUi']);
const { hasPermission } = usePermission();
const currentPath = ref('');
const currentBucket = ref('');
const bucketList = ref<OssContainer[]>([]);
const CardGrid = Card.Grid;
const CardMeta = Card.Meta;
onMounted(fetchBuckets);
const { L } = useLocalization(['AbpOssManagement', 'AbpUi']);
const currentPath = ref('');
const currentBucket = ref('');
const bucketList = ref<OssContainer[]>([]);
function fetchBuckets() {
getContainers({
prefix: '',
marker: '',
sorting: '',
skipCount: 0,
maxResultCount: 1000,
}).then((res) => {
bucketList.value = res.containers;
});
}
onMounted(fetchBuckets);
function handleBucketChange(bucket) {
currentBucket.value = bucket;
}
function fetchBuckets() {
getContainers({
prefix: '',
marker: '',
sorting: '',
skipCount: 0,
maxResultCount: 1000,
}).then((res) => {
bucketList.value = res.containers;
});
}
function handlePathChange(path) {
currentPath.value = path;
}
function handleBucketChange(bucket) {
currentBucket.value = bucket;
}
return {
L,
bucketList,
currentBucket,
currentPath,
handleBucketChange,
handlePathChange,
hasPermission,
};
},
});
function handlePathChange(path) {
currentPath.value = path;
}
</script>

47
apps/vue/src/views/oss-management/objects/components/OssPreviewModal.vue

@ -9,8 +9,8 @@
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, ref, unref, watch } from 'vue';
<script lang="ts" setup>
import { computed, ref, unref } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { ImagePreview } from '/@/components/Preview';
import { BasicModal, useModalInner } from '/@/components/Modal';
@ -18,36 +18,17 @@
import { generateOssUrl } from '/@/api/oss-management/oss';
import { useUserStoreWithOut } from '/@/store/modules/user';
export default defineComponent({
name: 'OssPreviewModal',
components: { BasicModal, ImagePreview },
setup() {
const { L } = useLocalization('AbpOssManagement');
const bucket = ref('');
const objects = ref<OssObject[]>([]);
const previewImages = ref<any[]>([]);
const [registerModal] = useModalInner((data) => {
bucket.value = data.bucket;
objects.value = data.objects;
});
const userStore = useUserStoreWithOut();
watch(
() => unref(objects),
(objs) => {
previewImages.value = objs.map((x) => {
return (
generateOssUrl(unref(bucket), x.path, x.name) + '?access_token=' + userStore.getToken
);
});
},
);
return {
L,
previewImages,
registerModal,
};
},
const { L } = useLocalization('AbpOssManagement');
const bucket = ref('');
const objects = ref<OssObject[]>([]);
const [registerModal] = useModalInner((data) => {
bucket.value = data.bucket;
objects.value = data.objects;
});
const previewImages = computed(() => {
const userStore = useUserStoreWithOut();
return objects.value.map((obj) => {
return generateOssUrl(unref(bucket), obj.path, obj.name) + '?access_token=' + userStore.getToken;
});
});
</script>

303
apps/vue/src/views/oss-management/objects/components/OssUploadModal.vue

@ -50,8 +50,8 @@
</BasicModal>
</template>
<script lang="ts">
import { computed, defineComponent, ref, unref, onMounted, onUnmounted, watch } from 'vue';
<script lang="ts" setup>
import { computed, ref, unref, onMounted, onUnmounted, watch } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { Tag, Tooltip } from 'ant-design-vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
@ -60,176 +60,157 @@
import { useUserStoreWithOut } from '/@/store/modules/user';
import Uploader from 'simple-uploader.js';
export default defineComponent({
name: 'OssUploadModal',
components: { BasicModal, BasicTable, TableAction, Tag, Tooltip },
setup() {
let uploader: any = null;
const { L } = useLocalization(['AbpOssManagement', 'AbpUi']);
const bucket = ref('');
const path = ref('');
const btnRef = ref<any>();
const [registerModal] = useModalInner((data) => {
path.value = data.path;
bucket.value = data.bucket;
});
const fileList = ref<Recordable[]>([]);
const [registerTable] = useTable({
rowKey: 'id',
columns: [
{
title: 'id',
dataIndex: 'id',
width: 1,
ifShow: false,
},
{
title: L('DisplayName:Name'),
dataIndex: 'name',
align: 'left',
width: 300,
sorter: true,
},
{
title: L('DisplayName:Size'),
dataIndex: 'size',
align: 'left',
width: 100,
sorter: true,
},
{
title: L('DisplayName:Status'),
dataIndex: 'status',
align: 'left',
width: 'auto',
sorter: true,
},
],
dataSource: fileList,
pagination: false,
striped: false,
useSearchForm: false,
showTableSetting: false,
bordered: false,
showIndexColumn: false,
canResize: false,
immediate: false,
actionColumn: {
width: 120,
title: L('Actions'),
dataIndex: 'action',
},
});
onMounted(() => {
const userStore = useUserStoreWithOut();
uploader = new Uploader({
target: uploadUrl,
testChunks: false,
//
maxChunkRetries: 3,
chunkRetryInterval: null,
successStatuses: [200, 201, 202, 204, 205],
permanentErrors: [400, 401, 403, 404, 415, 500, 501],
headers: {
// TODO: 使?
Authorization: `Bearer ${userStore.getToken}`,
},
processParams: (params: any) => {
params.bucket = unref(bucket);
params.path = unref(path);
return params;
},
});
// uploader.on('fileSuccess', _fileSuccess);
uploader.on('filesSubmitted', _filesSubmitted);
uploader.on('fileError', _fileError);
uploader.on('fileProgress', _fileProgress);
});
let uploader: any = null;
const { L } = useLocalization(['AbpOssManagement', 'AbpUi']);
const bucket = ref('');
const path = ref('');
const btnRef = ref<any>();
const [registerModal] = useModalInner((data) => {
path.value = data.path;
bucket.value = data.bucket;
});
const fileList = ref<Recordable[]>([]);
const [registerTable] = useTable({
rowKey: 'id',
columns: [
{
title: 'id',
dataIndex: 'id',
width: 1,
ifShow: false,
},
{
title: L('DisplayName:Name'),
dataIndex: 'name',
align: 'left',
width: 300,
sorter: true,
},
{
title: L('DisplayName:Size'),
dataIndex: 'size',
align: 'left',
width: 100,
sorter: true,
},
{
title: L('DisplayName:Status'),
dataIndex: 'status',
align: 'left',
width: 'auto',
sorter: true,
},
],
dataSource: fileList,
pagination: false,
striped: false,
useSearchForm: false,
showTableSetting: false,
bordered: false,
showIndexColumn: false,
canResize: false,
immediate: false,
actionColumn: {
width: 120,
title: L('Actions'),
dataIndex: 'action',
},
});
onUnmounted(() => {
// uploader.off('fileSuccess', _fileSuccess);
uploader.off('filesSubmitted', _filesSubmitted);
uploader.off('fileError', _fileError);
uploader.off('fileProgress', _fileProgress);
uploader = null;
});
onMounted(() => {
const userStore = useUserStoreWithOut();
uploader = new Uploader({
target: uploadUrl,
testChunks: false,
//
maxChunkRetries: 3,
chunkRetryInterval: null,
successStatuses: [200, 201, 202, 204, 205],
permanentErrors: [400, 401, 403, 404, 415, 500, 501],
headers: {
// TODO: 使?
Authorization: `Bearer ${userStore.getToken}`,
},
processParams: (params: any) => {
params.bucket = unref(bucket);
params.path = unref(path);
return params;
},
});
// uploader.on('fileSuccess', _fileSuccess);
uploader.on('filesSubmitted', _filesSubmitted);
uploader.on('fileError', _fileError);
uploader.on('fileProgress', _fileProgress);
});
watch(
() => unref(btnRef),
(btn) => {
uploader.assignBrowse(btn);
},
);
onUnmounted(() => {
// uploader.off('fileSuccess', _fileSuccess);
uploader.off('filesSubmitted', _filesSubmitted);
uploader.off('fileError', _fileError);
uploader.off('fileProgress', _fileProgress);
uploader = null;
});
function _filesSubmitted(_, files) {
files.forEach((f) => {
f.paused = true;
f.progress = '0 %';
});
fileList.value.push(...files);
}
watch(
() => unref(btnRef),
(btn) => {
uploader.assignBrowse(btn);
},
);
function _fileProgress(_, file) {
if (file._prevUploadedSize) {
file.progress = `${Math.floor((file._prevUploadedSize / file.size) * 100)} %`;
}
}
function _filesSubmitted(_, files) {
files.forEach((f) => {
f.paused = true;
f.progress = '0 %';
});
fileList.value.push(...files);
}
function _fileError(_, file, message) {
file.paused = true;
if (message) {
const formatedError = JSON.parse(message);
file.errorMsg = formatedError.error?.message;
}
}
function _fileProgress(_, file) {
if (file._prevUploadedSize) {
file.progress = `${Math.floor((file._prevUploadedSize / file.size) * 100)} %`;
}
}
function handleSelect() {
unref(btnRef)?.click();
}
function _fileError(_, file, message) {
file.paused = true;
if (message) {
const formatedError = JSON.parse(message);
file.errorMsg = formatedError.error?.message;
}
}
function handleResume(record) {
if (record.error) {
record.retry();
record.errorMsg = '';
}
record.resume();
}
function handleSelect() {
unref(btnRef)?.click();
}
function handlePause(record) {
record.pause();
}
function handleResume(record) {
if (record.error) {
record.retry();
record.errorMsg = '';
}
record.resume();
}
function handleCancel(record) {
record.cancel();
uploader.removeFile(record);
fileList.value = fileList.value.filter((f) => f.id !== record.id);
}
function handlePause(record) {
record.pause();
}
const fileSize = computed(() => {
return (size) => {
return Uploader.utils.formatSize(size);
};
});
function handleCancel(record) {
record.cancel();
uploader.removeFile(record);
fileList.value = fileList.value.filter((f) => f.id !== record.id);
}
const averageSpeed = computed(() => {
return (speed) => {
return `${Uploader.utils.formatSize(speed)} / s`;
};
});
const fileSize = computed(() => {
return (size) => {
return Uploader.utils.formatSize(size);
};
});
return {
L,
btnRef,
fileSize,
averageSpeed,
registerModal,
registerTable,
handleSelect,
handleResume,
handlePause,
handleCancel,
};
},
const averageSpeed = computed(() => {
return (speed) => {
return `${Uploader.utils.formatSize(speed)} / s`;
};
});
</script>

119
apps/vue/src/views/platform/dataDic/components/DataItemModal.vue

@ -4,88 +4,67 @@
</BasicModal>
</template>
<script lang="ts">
import { computed, defineComponent, ref, unref, watch } from 'vue';
<script lang="ts" setup>
import { computed, ref, unref, watch } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { DataItem } from '/@/api/platform/model/dataItemModel';
import { getDataItemFormSchemas } from './ModalData';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
import { createItem, updateItem } from '/@/api/platform/dataDic';
export default defineComponent({
name: 'DataItemModal',
components: {
BasicForm,
BasicModal,
},
emits: ['change', 'register'],
setup(_, { emit }) {
const dataItem = ref<DataItem>();
const { createMessage } = useMessage();
const { L } = useLocalization(['AppPlatform', 'AbpUi']);
const schemas = getDataItemFormSchemas();
watch(
() => unref(dataItem),
(item) => {
resetFields();
setFieldsValue(item);
},
{
immediate: false,
},
)
const emits = defineEmits(['change', 'register']);
const [registerForm, { validate, setFieldsValue, resetFields }] = useForm({
labelWidth: 120,
schemas,
showActionButtonGroup: false,
actionColOptions: {
span: 24,
},
});
const dataItem = ref<DataItem>();
const { createMessage } = useMessage();
const { L } = useLocalization(['AppPlatform', 'AbpUi']);
const schemas = getDataItemFormSchemas();
const [register, { changeLoading, closeModal }] = useModalInner((dataVal) => {
dataItem.value = dataVal;
});
watch(
() => unref(dataItem),
(item) => {
resetFields();
setFieldsValue(item);
},
{
immediate: false,
},
)
const title = computed(() => {
if (unref(dataItem)?.id) {
return L('Data:EditItem');
}
return L('Data:AppendItem');
});
const [registerForm, { validate, setFieldsValue, resetFields }] = useForm({
labelWidth: 120,
schemas,
showActionButtonGroup: false,
actionColOptions: {
span: 24,
},
});
function handleSubmit() {
validate().then((input) => {
changeLoading(true);
const api = input.id
? updateItem(input.dataId, input.name, input)
: createItem(input.dataId, input);
api.then(() => {
createMessage.success(L('Successful'));
emit('change', input.dataId);
closeModal();
})
.finally(() => {
changeLoading(false);
});
});
}
const [register, { changeLoading, closeModal }] = useModalInner((dataVal) => {
dataItem.value = dataVal;
});
return {
L,
title,
registerForm,
register,
dataItem,
handleSubmit,
};
},
const title = computed(() => {
if (unref(dataItem)?.id) {
return L('Data:EditItem');
}
return L('Data:AppendItem');
});
function handleSubmit() {
validate().then((input) => {
changeLoading(true);
const api = input.id
? updateItem(input.dataId, input.name, input)
: createItem(input.dataId, input);
api.then(() => {
createMessage.success(L('Successful'));
emits('change', input.dataId);
closeModal();
}).finally(() => {
changeLoading(false);
});
});
}
</script>

176
apps/vue/src/views/platform/dataDic/components/DataItemTable.vue

@ -31,119 +31,99 @@
<DataItemModal @register="registerModal" @change="fetchItems" />
</template>
<script lang="ts">
import { computed, defineComponent, ref, createVNode, watch } from 'vue';
<script lang="ts" setup>
import { computed, ref, createVNode, watch } from 'vue';
import { getDataColumns } from './TableData';
import DataItemModal from './DataItemModal.vue';
import { Modal, Switch } from 'ant-design-vue';
import { Switch } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useModal } from '/@/components/Modal';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { DataItem } from '/@/api/platform/model/dataItemModel';
import { get, removeItem } from '/@/api/platform/dataDic';
import DataItemModal from './DataItemModal.vue';
const props = {
dataId: { type: String, retuired: true },
} as const;
export default defineComponent({
name: 'DataItemTable',
components: {
BasicTable,
TableAction,
DataItemModal,
Switch,
const emits = defineEmits(['reload']);
const props = defineProps({
dataId: {
type: String,
retuired: true,
},
props,
emits: ['reload'],
setup(props, { emit }) {
const { L } = useLocalization(['AppPlatform', 'AbpUi']);
const dataItems = ref<DataItem[]>([]);
const [registerTable] = useTable({
rowKey: 'id',
title: L('Data:Items'),
columns: getDataColumns(),
dataSource: dataItems,
bordered: true,
canResize: true,
showTableSetting: true,
rowSelection: { type: 'checkbox' },
actionColumn: {
width: 160,
title: L('Actions'),
dataIndex: 'action',
},
});
const [registerModal, { openModal }] = useModal();
});
const isEnableNew = computed(() => {
if (props.dataId && props.dataId !== '') {
return true;
}
return false;
});
const { createMessage, createConfirm } = useMessage();
const { L } = useLocalization(['AppPlatform', 'AbpUi']);
const dataItems = ref<DataItem[]>([]);
const [registerTable] = useTable({
rowKey: 'id',
title: L('Data:Items'),
columns: getDataColumns(),
dataSource: dataItems,
bordered: true,
canResize: true,
showTableSetting: true,
rowSelection: { type: 'checkbox' },
actionColumn: {
width: 160,
title: L('Actions'),
dataIndex: 'action',
},
});
const [registerModal, { openModal }] = useModal();
watch(
() => props.dataId,
(dataId) => {
dataItems.value = [];
if (dataId) {
fetchItems(dataId);
}
},
{
immediate: true,
},
)
const isEnableNew = computed(() => {
if (props.dataId && props.dataId !== '') {
return true;
}
return false;
});
function fetchItems(dataId: string) {
get(dataId).then((res) => {
dataItems.value = res.items;
});
watch(
() => props.dataId,
(dataId) => {
dataItems.value = [];
if (dataId) {
fetchItems(dataId);
}
},
{
immediate: true,
},
)
function handleAppendItem() {
openModal(true, { dataId: props.dataId });
}
function fetchItems(dataId: string) {
get(dataId).then((res) => {
dataItems.value = res.items;
});
}
function handleEdit(record) {
openModal(true, { dataId: props.dataId, ...record });
}
function handleAppendItem() {
openModal(true, { dataId: props.dataId });
}
function handleDelete(record: Recordable) {
Modal.confirm({
title: L('AreYouSure'),
icon: createVNode(ExclamationCircleOutlined),
content: createVNode(
'div',
{ style: 'color:red;' },
L('ItemWillBeDeletedMessageWithFormat', [record.displayName] as Recordable),
),
onOk: () => {
removeItem(props.dataId!, record.name).then(() => {
emit('reload');
fetchItems(props.dataId!);
});
},
});
}
function handleEdit(record) {
openModal(true, { dataId: props.dataId, ...record });
}
return {
L,
isEnableNew,
registerTable,
dataItems,
registerModal,
openModal,
fetchItems,
handleAppendItem,
handleEdit,
handleDelete,
};
},
});
function handleDelete(record: Recordable) {
createConfirm({
iconType: 'error',
title: L('AreYouSure'),
icon: createVNode(ExclamationCircleOutlined),
content: createVNode(
'div',
{ style: 'color:red;' },
L('ItemWillBeDeletedMessageWithFormat', [record.displayName] as Recordable),
),
onOk: () => {
removeItem(props.dataId!, record.name)
.then(() => {
createMessage.success(L('SuccessfullyDeleted'));
emits('reload');
fetchItems(props.dataId!);
});
},
});
}
</script>

108
apps/vue/src/views/platform/dataDic/components/DataModal.vue

@ -9,78 +9,60 @@
</BasicModal>
</template>
<script lang="ts">
import { defineComponent, ref, nextTick } from 'vue';
<script lang="ts" setup>
import { ref, nextTick } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { get, create, update } from '/@/api/platform/dataDic';
import { getDateFormSchemas } from './ModalData';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm } from '/@/components/Form/index';
export default defineComponent({
name: 'DataModal',
components: {
BasicForm,
BasicModal,
},
emits: ['register', 'change'],
setup(_, { emit }) {
const { createMessage } = useMessage();
const { L } = useLocalization('AppPlatform');
const schemas = getDateFormSchemas();
const title = ref('');
const [registerForm, { validate, setFieldsValue, resetFields }] = useForm({
labelWidth: 120,
schemas,
showActionButtonGroup: false,
actionColOptions: {
span: 24,
},
});
const [register, { changeLoading, closeModal }] = useModalInner((dataVal) => {
nextTick(() => {
fetchData(dataVal.id);
});
});
function fetchData(id?: string) {
resetFields();
if (!id) {
title.value = L('Data:AddNew');
} else {
get(id).then((data) => {
setFieldsValue(data);
title.value = L('Data:Edit');
});
}
}
const emits = defineEmits(['register', 'change']);
function handleSubmit() {
validate().then((input) => {
changeLoading(true);
const api = input.id ? update(input.id, input) : create(input);
api.then((data) => {
createMessage.success(L('Successful'));
closeModal();
emit('change', data);
}).finally(() => {
changeLoading(false);
});
});
}
const { createMessage } = useMessage();
const { L } = useLocalization('AppPlatform');
const schemas = getDateFormSchemas();
const title = ref('');
return {
L,
title,
registerForm,
register,
handleSubmit,
};
const [registerForm, { validate, setFieldsValue, resetFields }] = useForm({
labelWidth: 120,
schemas,
showActionButtonGroup: false,
actionColOptions: {
span: 24,
},
});
const [register, { changeLoading, closeModal }] = useModalInner((dataVal) => {
nextTick(() => {
fetchData(dataVal.id);
});
});
function fetchData(id?: string) {
resetFields();
if (!id) {
title.value = L('Data:AddNew');
} else {
get(id).then((data) => {
setFieldsValue(data);
title.value = L('Data:Edit');
});
}
}
function handleSubmit() {
validate().then((input) => {
changeLoading(true);
const api = input.id ? update(input.id, input) : create(input);
api.then((data) => {
createMessage.success(L('Successful'));
closeModal();
emits('change', data);
}).finally(() => {
changeLoading(false);
});
});
}
</script>

162
apps/vue/src/views/platform/dataDic/components/DataTree.vue

@ -17,112 +17,90 @@
</Card>
</template>
<script lang="ts">
import { defineComponent, ref, onMounted } from 'vue';
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { Modal, Card } from 'ant-design-vue';
import { Card } from 'ant-design-vue';
import { useModal } from '/@/components/Modal';
import { BasicTree, ContextMenuItem } from '/@/components/Tree/index';
import { listToTree } from '/@/utils/helper/treeHelper';
import { getAll, remove } from '/@/api/platform/dataDic';
import { Data } from '/@/api/platform/model/dataModel';
import DataModal from './DataModal.vue';
import DataItemModal from './DataItemModal.vue';
export default defineComponent({
name: 'DataTree',
components: {
Card,
BasicTree,
DataModal,
DataItemModal,
},
emits: ['change', 'append-item'],
setup(_, { emit }) {
const { L } = useLocalization(['AppPlatform', 'AbpUi']);
const title = L('DisplayName:DataDictionary');
const treeData = ref<Data[]>([]);
const replaceFields = ref({
title: 'displayName',
key: 'id',
value: 'id',
});
const [registerItemModal, { openModal: openItemModal }] = useModal();
const [registerDataModal, { openModal: openDataModal }] = useModal();
const emits = defineEmits(['change', 'append-item']);
onMounted(onLoadAllDataDic);
const { createMessage, createConfirm } = useMessage();
const { L } = useLocalization(['AppPlatform', 'AbpUi']);
const title = L('DisplayName:DataDictionary');
const treeData = ref<Data[]>([]);
const replaceFields = ref({
title: 'displayName',
key: 'id',
value: 'id',
});
const [registerItemModal, { openModal: openItemModal }] = useModal();
const [registerDataModal, { openModal: openDataModal }] = useModal();
function getContentMenus(node: any): ContextMenuItem[] {
return [
{
label: L('Data:Edit'),
handler: () => {
openDataModal(true, { id: node.eventKey });
},
icon: 'ant-design:edit-outlined',
},
{
label: L('Data:AddNew'),
handler: () => {
openDataModal(true, { parentId: node.eventKey });
},
icon: 'ant-design:plus-outlined',
},
{
label: L('Data:AppendItem'),
handler: () => {
openItemModal(true, { dataId: node.eventKey }, true);
},
icon: 'ant-design:plus-square-outlined',
},
{
label: L('Data:Delete'),
handler: () => {
Modal.warning({
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
remove(node.eventKey).then(() => {
onLoadAllDataDic();
});
},
onMounted(onLoadAllDataDic);
function getContentMenus(node: any): ContextMenuItem[] {
return [
{
label: L('Data:Edit'),
handler: () => {
openDataModal(true, { id: node.eventKey });
},
icon: 'ant-design:edit-outlined',
},
{
label: L('Data:AddNew'),
handler: () => {
openDataModal(true, { parentId: node.eventKey });
},
icon: 'ant-design:plus-outlined',
},
{
label: L('Data:AppendItem'),
handler: () => {
openItemModal(true, { dataId: node.eventKey }, true);
},
icon: 'ant-design:plus-square-outlined',
},
{
label: L('Data:Delete'),
handler: () => {
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessage'),
okCancel: true,
onOk: () => {
remove(node.eventKey).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
onLoadAllDataDic();
});
},
icon: 'ant-design:delete-outlined',
},
];
}
function onLoadAllDataDic() {
getAll().then((res) => {
treeData.value = listToTree(res.items, {
pid: 'parentId',
});
});
}
},
icon: 'ant-design:delete-outlined',
},
];
}
function handleNodeChange(selectKeys: String[]) {
if (selectKeys.length > 0) {
emit('change', selectKeys[0]);
}
}
function onLoadAllDataDic() {
getAll().then((res) => {
treeData.value = listToTree(res.items, {
pid: 'parentId',
});
});
}
return {
L,
title,
treeData,
replaceFields,
registerDataModal,
openDataModal,
registerItemModal,
openItemModal,
getContentMenus,
handleNodeChange,
onLoadAllDataDic,
};
},
});
function handleNodeChange(selectKeys: String[]) {
if (selectKeys.length > 0) {
emits('change', selectKeys[0]);
}
}
</script>

36
apps/vue/src/views/platform/dataDic/index.vue

@ -10,34 +10,20 @@
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import { useI18n } from '/@/hooks/web/useI18n';
export default {
name: 'DataDictionary',
};
</script>
<script lang="ts" setup>
import { ref } from 'vue';
import { Row, Col } from 'ant-design-vue';
import DataTree from './components/DataTree.vue';
import DataItemTable from './components/DataItemTable.vue';
import { Row, Col } from 'ant-design-vue';
export default defineComponent({
name: 'DataDictionary',
components: {
DataTree,
DataItemTable,
Row,
Col,
},
setup() {
const { t } = useI18n();
const dataId = ref('');
const dataId = ref('');
return {
t,
dataId,
};
},
methods: {
handleDataChange(id: string) {
this.dataId = id;
},
},
});
function handleDataChange(id: string) {
dataId.value = id;
}
</script>

94
apps/vue/src/views/platform/layout/components/LayoutModal.vue

@ -8,9 +8,8 @@
/>
</template>
<script lang="ts">
import { defineComponent, ref, computed } from 'vue';
<script lang="ts" setup>
import { ref, computed } from 'vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { useModalInner } from '/@/components/Modal';
import { BasicModalForm } from '/@/components/ModalForm';
@ -18,60 +17,43 @@
import { Layout } from '/@/api/platform/model/layoutModel';
import { create, update } from '/@/api/platform/layout';
export default defineComponent({
name: 'LayoutModal',
components: {
BasicModalForm,
},
emits: ['change', 'register'],
setup() {
const { L } = useLocalization('AppPlatform');
const layout = ref<Layout>({} as Layout);
const formItems = getModalFormSchemas(layout.value);
const [register, { closeModal }] = useModalInner((dataVal) => {
layout.value = dataVal;
});
const emits = defineEmits(['change', 'register']);
const title = computed(() => {
if (layout.value.id) {
return L('Layout:EditByName', [layout.value.displayName] as Recordable);
}
return L('Layout:AddNew');
});
const { L } = useLocalization('AppPlatform');
const layout = ref<Layout>({} as Layout);
const formItems = getModalFormSchemas(layout.value);
const [register, { closeModal }] = useModalInner((dataVal) => {
layout.value = dataVal;
});
return {
L,
layout,
register,
closeModal,
formItems,
title,
};
},
methods: {
handleSaveChanges(data) {
const api =
data.id === undefined
? create({
dataId: data.dataId,
framework: data.framework,
name: data.name,
displayName: data.displayName,
description: data.description,
redirect: data.redirect,
path: data.path,
})
: update(data.id, {
name: data.name,
displayName: data.displayName,
description: data.description,
redirect: data.redirect,
path: data.path,
});
return api.then(() => {
this.$emit('change');
});
},
},
const title = computed(() => {
if (layout.value.id) {
return L('Layout:EditByName', [layout.value.displayName] as Recordable);
}
return L('Layout:AddNew');
});
function handleSaveChanges(data) {
const api = data.id === undefined
? create({
dataId: data.dataId,
framework: data.framework,
name: data.name,
displayName: data.displayName,
description: data.description,
redirect: data.redirect,
path: data.path,
})
: update(data.id, {
name: data.name,
displayName: data.displayName,
description: data.description,
redirect: data.redirect,
path: data.path,
});
return api.then(() => {
emits('change');
closeModal();
});
}
</script>

105
apps/vue/src/views/platform/layout/components/LayoutTable.vue

@ -26,15 +26,13 @@
</template>
</template>
</BasicTable>
<LayoutModal @change="reloadTable" @register="registerLayoutModal" :layout-id="layoutId" />
<LayoutModal @change="reload" @register="registerLayoutModal" />
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
<script lang="ts" setup>
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { Modal } from 'ant-design-vue';
import { useModal } from '/@/components/Modal';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { getDataColumns } from './TableData';
@ -42,64 +40,49 @@
import { getList, deleteById } from '/@/api/platform/layout';
import { formatPagedRequest } from '/@/utils/http/abp/helper';
import LayoutModal from './LayoutModal.vue';
export default defineComponent({
name: 'LayoutTable',
components: {
BasicTable,
TableAction,
LayoutModal,
},
setup() {
const { L } = useLocalization(['AppPlatform', 'AbpUi']);
const layoutId = ref('');
const [registerTable, { reload: reloadTable }] = useTable({
rowKey: 'id',
title: L('DisplayName:Layout'),
columns: getDataColumns(),
api: getList,
beforeFetch: formatPagedRequest,
bordered: true,
canResize: true,
showTableSetting: true,
useSearchForm: true,
formConfig: getSearchFormSchemas(),
rowSelection: { type: 'checkbox' },
actionColumn: {
width: 160,
title: L('Actions'),
dataIndex: 'action',
},
});
const [registerLayoutModal, { openModal: openLayoutModal }] = useModal();
return {
L,
layoutId,
reloadTable,
registerTable,
openLayoutModal,
registerLayoutModal,
};
const { createMessage, createConfirm } = useMessage();
const { L } = useLocalization(['AppPlatform', 'AbpUi']);
const [registerTable, { reload }] = useTable({
rowKey: 'id',
title: L('DisplayName:Layout'),
columns: getDataColumns(),
api: getList,
beforeFetch: formatPagedRequest,
bordered: true,
canResize: true,
showTableSetting: true,
useSearchForm: true,
formConfig: getSearchFormSchemas(),
rowSelection: { type: 'checkbox' },
actionColumn: {
width: 160,
title: L('Actions'),
dataIndex: 'action',
},
methods: {
handleAddNew() {
this.openLayoutModal(true, {}, true);
},
handleEdit(record: Recordable) {
this.openLayoutModal(true, record, true);
},
handleDelete(record: Recordable) {
Modal.warning({
title: this.L('AreYouSure'),
content: this.L('ItemWillBeDeletedMessageWithFormat', [record.displayName] as Recordable),
okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
this.reloadTable();
});
},
});
const [registerLayoutModal, { openModal: openLayoutModal }] = useModal();
function handleAddNew() {
openLayoutModal(true, {});
}
function handleEdit(record: Recordable) {
openLayoutModal(true, record);
}
function handleDelete(record: Recordable) {
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessageWithFormat', [record.displayName]),
okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reload();
});
},
},
});
});
}
</script>

77
apps/vue/src/views/platform/menu/components/MenuDrawer.vue

@ -22,58 +22,45 @@
</BasicDrawer>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
<script lang="ts" setup>
import { nextTick, ref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { TabForm, FormActionType } from '/@/components/Form';
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
import { basicProps } from './props';
import { Menu } from '/@/api/platform/model/menuModel';
import { useMenuFormContext } from '../hooks/useMenuFormContext';
export default defineComponent({
name: 'MenuDrawer',
components: {
BasicDrawer,
TabForm,
},
props: basicProps,
emits: ['change', 'register'],
setup(props) {
const menu = ref<Menu>({} as Menu);
const framework = ref<string | undefined>('');
const formElRef = ref<Nullable<FormActionType>>(null);
const { formTitle, getFormSchemas, handleFormSubmit, fetchLayoutResource } =
useMenuFormContext({
menuModel: menu,
formElRef: formElRef,
framework: framework,
});
const emits = defineEmits(['change', 'register']);
const props = defineProps(basicProps);
const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (dataVal) => {
setDrawerProps({ confirmLoading: false });
menu.value = dataVal;
framework.value = props.framework;
fetchLayoutResource(dataVal.layoutId);
});
const { createMessage } = useMessage();
const { L } = useLocalization(['AppPlatform', 'AbpUi']);
const menu = ref<Menu>({} as Menu);
const framework = ref<string | undefined>('');
const formElRef = ref<Nullable<FormActionType>>(null);
const { formTitle, getFormSchemas, handleFormSubmit, fetchLayoutResource } =
useMenuFormContext({
menuModel: menu,
formElRef: formElRef,
framework: framework,
});
return {
formTitle,
formElRef,
handleFormSubmit,
getFormSchemas,
registerDrawer,
closeDrawer,
};
},
methods: {
handleSubmit() {
this.handleFormSubmit()?.then(() => {
this.closeDrawer();
this.$emit('change');
});
},
},
const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner((dataVal) => {
menu.value = dataVal;
framework.value = props.framework;
nextTick(() => {
setDrawerProps({ confirmLoading: false });
fetchLayoutResource(dataVal.layoutId);
});
});
function handleSubmit() {
handleFormSubmit()?.then(() => {
createMessage.success(L('Successful'));
closeDrawer();
emits('change');
});
}
</script>

140
apps/vue/src/views/platform/menu/components/MenuTable.vue

@ -30,94 +30,80 @@
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import { Modal } from 'ant-design-vue';
<script lang="ts" setup>
import { ref } from 'vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useDrawer } from '/@/components/Drawer';
import MenuDrawer from './MenuDrawer.vue';
import { getDataColumns } from './TableData';
import { getSearchFormSchemas } from './ModalData';
import { getAll, getById, deleteById } from '/@/api/platform/menu';
import { listToTree } from '/@/utils/helper/treeHelper';
export default defineComponent({
name: 'MenuTable',
components: {
BasicTable,
TableAction,
MenuDrawer,
import MenuDrawer from './MenuDrawer.vue';
const { createMessage, createConfirm } = useMessage();
const { L } = useLocalization(['AppPlatform', 'AbpUi']);
const useFramework = ref('');
const [registerTable, { reload }] = useTable({
rowKey: 'id',
title: L('DisplayName:Menus'),
columns: getDataColumns(),
api: getAll,
beforeFetch: (request) => {
// ,
useFramework.value = request.framework;
return request;
},
setup() {
const { L } = useLocalization(['AppPlatform', 'AbpUi']);
const useFramework = ref('');
const [registerTable, { reload: reloadTable }] = useTable({
rowKey: 'id',
title: L('DisplayName:Menus'),
columns: getDataColumns(),
api: getAll,
beforeFetch: (request) => {
// ,
useFramework.value = request.framework;
return request;
},
afterFetch: (result) => {
return listToTree(result, {
id: 'id',
pid: 'parentId',
});
},
pagination: false,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: false,
formConfig: getSearchFormSchemas(),
actionColumn: {
width: 160,
title: L('Actions'),
dataIndex: 'action',
},
afterFetch: (result) => {
return listToTree(result, {
id: 'id',
pid: 'parentId',
});
},
pagination: false,
striped: false,
useSearchForm: true,
showTableSetting: true,
bordered: true,
showIndexColumn: false,
canResize: false,
formConfig: getSearchFormSchemas(),
actionColumn: {
width: 160,
title: L('Actions'),
dataIndex: 'action',
},
});
const [registerDrawer, { openDrawer }] = useDrawer();
const [registerDrawer, { openDrawer }] = useDrawer();
function handleAddNew() {
openDrawer(true, {});
}
return {
L,
registerTable,
reloadTable,
registerDrawer,
openDrawer,
useFramework,
};
},
methods: {
handleAddNew() {
this.openDrawer(true, {}, true);
},
handleEdit(record: Recordable) {
getById(record.id).then((menu) => {
this.openDrawer(true, menu, true);
});
},
handleDelete(record: Recordable) {
Modal.warning({
title: this.L('AreYouSure'),
content: this.L('ItemWillBeDeletedMessageWithFormat', [record.displayName] as Recordable),
okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
this.reloadTable();
});
},
function handleEdit(record: Recordable) {
getById(record.id).then((menu) => {
openDrawer(true, menu);
});
}
function handleDelete(record: Recordable) {
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('ItemWillBeDeletedMessageWithFormat', [record.displayName]),
okCancel: true,
onOk: () => {
deleteById(record.id).then(() => {
createMessage.success(L('SuccessfullyDeleted'));
reload();
});
},
handleChange() {
this.reloadTable();
},
},
});
});
}
function handleChange() {
reload();
}
</script>

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save