Commit bed5d170 authored by Sendya's avatar Sendya

fix: some bug

parent 1cb1789c
......@@ -3,7 +3,7 @@ module.exports = {
test: {
presets: [['@babel/preset-env', { targets: { node: true } }]],
plugins: [
['@vue/babel-plugin-jsx', { mergeProps: false }],
'@vue/babel-plugin-jsx',
'@babel/plugin-proposal-optional-chaining',
'@babel/plugin-transform-object-assign',
'@babel/plugin-proposal-object-rest-spread',
......
import { defineComponent } from 'vue';
import { useRoute } from 'vue-router';
export default defineComponent({
setup() {
return () => <div>Form1</div>;
const route = useRoute();
return () => (
<div>
<h1>Form: {route.meta.title}</h1>
<pre>{JSON.stringify(route.meta, null, 4)}</pre>
</div>
);
},
});
import { defineComponent } from 'vue';
import { useRoute } from 'vue-router';
export default defineComponent({
setup() {
return () => <div>Page1</div>;
const route = useRoute();
return () => (
<div>
<h1>Page: {route.meta.title}</h1>
<pre>{JSON.stringify(route.meta, null, 4)}</pre>
</div>
);
},
});
import { defineComponent } from 'vue';
import { Button, Space, Select, Switch } from 'ant-design-vue';
import { globalState as state } from '../state';
export default defineComponent({
setup() {
return () => <div>Welcome</div>;
return () => (
<div>
<div>Welcome</div>
<Space>
<Button
onClick={() => {
state.navTheme = state.navTheme === 'dark' ? 'light' : 'dark';
}}
>
Theme Switch
</Button>
<Select
value={state.layout}
onChange={val => {
state.layout = val;
}}
style={{ width: '150px' }}
>
<Select.Option value="side">Side</Select.Option>
<Select.Option value="top">Top</Select.Option>
<Select.Option value="mix">Mix</Select.Option>
</Select>
<Switch
checkedChildren="Fixed Header"
unCheckedChildren="UnFixed Header"
checked={state.fixedHeader}
onChange={() => {
state.fixedHeader = !state.fixedHeader;
}}
/>
<Switch
checkedChildren="Fixed SideBar"
unCheckedChildren="UnFixed SideBar"
checked={state.fixSiderbar}
onChange={() => {
state.fixSiderbar = !state.fixSiderbar;
}}
/>
</Space>
<p>
<p>block</p>
...
<br />
long text..
</p>
<p>
<p>block</p>
...
<br />
long text..
</p>
<p>
<p>block</p>
...
<br />
long text..
</p>
<p>
<p>block</p>
...
<br />
long text..
</p>
<p>
<p>block</p>
...
<br />
long text..
</p>
<p>
<p>block</p>
...
<br />
long text..
</p>
<p>
<p>block</p>
...
<br />
long text..
</p>
<p>
<p>block</p>
...
<br />
long text..
</p>
</div>
);
},
});
import 'ant-design-vue/dist/antd.less';
import { createApp, defineComponent, onMounted, watch, ref, reactive } from 'vue';
import { createRouter, createWebHashHistory } from 'vue-router';
import { Button, Avatar, Space, message } from 'ant-design-vue';
import { createApp, defineComponent, watch, ref } from 'vue';
import { createRouter, createWebHashHistory, useRoute } from 'vue-router';
import { Avatar } from 'ant-design-vue';
import { UserOutlined } from '@ant-design/icons-vue';
import { default as ProLayout } from '../src/';
import { createRouteContext, RouteContextProps } from '../src/RouteContext';
import { menus } from './menus';
import { createRouteContext } from '../src/RouteContext';
import { globalState as state } from './state';
import registerIcons from './_util/icons';
// demo pages
......@@ -17,28 +18,7 @@ const BasicLayout = defineComponent({
name: 'BasicLayout',
inheritAttrs: false,
setup() {
const state = reactive<RouteContextProps>({
collapsed: false,
openKeys: ['/dashboard'],
setOpenKeys: (keys: string[]) => (state.openKeys = keys),
selectedKeys: ['/welcome'],
setSelectedKeys: (keys: string[]) => {
console.log('keys', keys);
state.selectedKeys = keys;
},
navTheme: 'dark',
isMobile: false,
fixSiderbar: false,
fixedHeader: false,
menuData: menus,
sideWidth: 208,
splitMenus: true,
hasSideMenu: true,
hasHeader: true,
hasFooterToolbar: false,
setHasFooterToolbar: (has: boolean) => (state.hasFooterToolbar = has),
});
const route = useRoute();
const [RouteContextProvider] = createRouteContext();
const cacheOpenKeys = ref<string[]>([]);
......@@ -61,8 +41,7 @@ const BasicLayout = defineComponent({
return () => (
<RouteContextProvider value={state}>
<ProLayout
v-model={[state.collapsed, 'collapsed']}
layout={'mix'}
layout={state.layout}
navTheme={state.navTheme}
i18n={(key: string) => key}
isMobile={state.isMobile}
......@@ -73,16 +52,28 @@ const BasicLayout = defineComponent({
contentStyle={{ minHeight: '300px' }}
siderWidth={state.sideWidth}
splitMenus={state.splitMenus}
collapsed={state.collapsed}
openKeys={state.openKeys}
selectedKeys={state.selectedKeys}
{...{
'onUpdate:collapsed': $event => (state.collapsed = $event),
'onUpdate:openKeys': $event => (state.openKeys = $event),
'onUpdate:selectedKeys': () => {
const matched = route.matched.concat().map(item => item.path);
matched.shift();
state.selectedKeys = matched;
},
}}
v-slots={{
rightContentRender: () => (
<div style="margin-right: 16px;">
<div style={{ marginRight: '16px' }}>
<Avatar icon={<UserOutlined />} /> Sendya
</div>
),
menuHeaderRender: () => (
<a>
<img src="https://gw.alipayobjects.com/zos/antfincdn/PmY%24TNNDBI/logo.svg" />
{state.collapsed ? null : <h1>Pro Preview</h1>}
{state.collapsed && state.layout !== 'mix' ? null : <h1>Pro Preview</h1>}
</a>
),
}}
......
import { reactive } from 'vue';
import { menus } from './menus';
import { RouteContextProps } from '../src/RouteContext';
export const globalState = reactive<RouteContextProps>({
collapsed: false,
openKeys: ['/dashboard'],
selectedKeys: ['/welcome'],
layout: 'mix',
navTheme: 'dark',
isMobile: false,
fixSiderbar: false,
fixedHeader: false,
menuData: menus,
sideWidth: 208,
splitMenus: true,
hasSideMenu: true,
hasHeader: true,
hasFooterToolbar: false,
setHasFooterToolbar: (has: boolean) => (globalState.hasFooterToolbar = has),
});
import { computed, FunctionalComponent, CSSProperties, VNodeChild, VNode } from 'vue';
import { computed, FunctionalComponent, CSSProperties, VNodeChild, VNode, ComputedRef } from 'vue';
import 'ant-design-vue/es/layout/style';
import Layout from 'ant-design-vue/es/layout';
import { withInstall } from 'ant-design-vue/es/_util/type';
......@@ -73,11 +73,11 @@ const ProLayout: FunctionalComponent<BasicLayoutProps> = (props, { emit, slots,
const handleCollapse = (collapsed: boolean) => {
emit('update:collapsed', collapsed);
};
const handleOpenChange = (openKeys: string[] | false): void => {
openKeys && emit('update:openKeys', openKeys);
const handleOpenKeys = (openKeys: string[] | false): void => {
openKeys && emit('update:open-keys', openKeys);
};
const handleSelect = (selectedKeys: string[] | false): void => {
selectedKeys && emit('update:selectedKeys', selectedKeys);
selectedKeys && emit('update:selected-keys', selectedKeys);
};
const baseClassName = computed(() => `${props.prefixCls}-basicLayout`);
// gen className
......@@ -116,13 +116,13 @@ const ProLayout: FunctionalComponent<BasicLayoutProps> = (props, { emit, slots,
const headerDom = headerRender(
{
...props,
hasSiderMenu: isTop.value,
hasSiderMenu: !isTop.value,
menuData,
isMobile,
collapsed,
onCollapse,
// onSelect: handleSelect,
// onOpenChange: handleOpenChange,
onSelect: handleSelect,
onOpenKeys: handleOpenKeys,
customHeaderRender,
rightContentRender,
headerTitleRender:
......@@ -150,9 +150,11 @@ const ProLayout: FunctionalComponent<BasicLayoutProps> = (props, { emit, slots,
menuHeaderRenderFunc || (menuHeaderRenderSlot && (() => menuHeaderRenderSlot()))
}
onCollapse={handleCollapse}
onSelect={handleSelect}
onOpenKeys={handleOpenKeys}
/>
)}
<Layout>
<Layout style={contentStyle}>
{headerDom}
<WrapContent style={props.contentStyle}>{slots.default?.()}</WrapContent>
{footerRender !== false && footerRender && footerRender}
......@@ -166,7 +168,7 @@ const ProLayout: FunctionalComponent<BasicLayoutProps> = (props, { emit, slots,
ProLayout.inheritAttrs = false;
ProLayout.displayName = 'ProLayout';
ProLayout.emits = ['update:collapsed', 'update:openKeys', 'update:selectedKeys'];
ProLayout.emits = ['update:collapsed', 'update:open-keys', 'update:selected-keys'];
ProLayout.props = {
prefixCls: PropTypes.string.def('ant-pro'),
title: PropTypes.VNodeChild.def('Ant Design Pro'),
......
......@@ -29,6 +29,8 @@ export interface GlobalHeaderProps extends Partial<PureSettings> {
menuHeaderRender?: SiderMenuProps['menuHeaderRender'];
collapsedButtonRender?: SiderMenuProps['collapsedButtonRender'];
splitMenus?: boolean;
onOpenKeys?: (openKeys: WithFalse<string[]>) => void;
onSelect?: (selectedKeys: WithFalse<string[]>) => void;
}
const renderLogo = (
......
......@@ -75,7 +75,6 @@ export const HeaderView = defineComponent({
navTheme,
onCollapse,
} = toRefs(props);
console.log('HeaderView', props);
const context = useRouteContext();
const isTop = computed(() => props.layout === 'top' || props.layout === 'mix');
const needFixedHeader = computed(() => fixedHeader.value || layout.value === 'mix');
......@@ -95,7 +94,6 @@ export const HeaderView = defineComponent({
{headerContentRender && headerContentRender.value && headerContentRender.value(props)}
</GlobalHeader>
);
console.log('renderContent', isTop.value, clearMenuData.value);
if (isTop.value && !isMobile.value) {
defaultDom = (
<TopNavHeader
......@@ -127,7 +125,7 @@ export const HeaderView = defineComponent({
{needFixedHeader.value && (
<Header
style={{
height: headerHeight.value,
height: `${headerHeight.value}px`,
lineHeight: `${headerHeight.value}px`,
background: 'transparent',
}}
......
......@@ -143,7 +143,7 @@ const LazyIcon = (props: any) => {
if (isVNode(icon)) {
return icon;
}
const LazyIcon = resolveComponent(icon);
const LazyIcon = resolveComponent(icon) as any;
return (typeof LazyIcon === 'function' && <LazyIcon />) || null;
};
......
......@@ -11,6 +11,7 @@ import { useProProvider } from '../ProProvider';
import { useRouteContext } from '../RouteContext';
import { getMenuFirstChildren } from '../utils';
import './index.less';
import { emit } from 'process';
const { Sider } = Layout;
......@@ -36,8 +37,8 @@ export interface SiderMenuProps
onMenuHeaderClick?: (e: MouseEvent) => void;
fixed?: boolean;
hide?: boolean;
// onOpenChange?: (openKeys: WithFalse<string[]>) => void;
// onSelect?: (selectedKeys: WithFalse<string[]>) => void;
onOpenKeys?: (openKeys: WithFalse<string[]>) => void;
onSelect?: (selectedKeys: WithFalse<string[]>) => void;
}
export const defaultRenderLogo = (logo: RenderVNodeType): RenderVNodeType => {
......@@ -86,10 +87,11 @@ export const defaultRenderCollapsedButton = (collapsed?: boolean): RenderVNodeTy
const SiderMenu: FunctionalComponent<SiderMenuProps> = (props: SiderMenuProps) => {
const {
// menuData,
collapsed,
siderWidth,
onCollapse,
onOpenKeys,
onSelect,
breakpoint,
collapsedWidth = 48,
menuExtraRender = false,
......@@ -118,7 +120,6 @@ const SiderMenu: FunctionalComponent<SiderMenuProps> = (props: SiderMenuProps) =
});
const hasSide = computed(() => props.layout === 'mix' && context.splitMenus);
const flatMenuData = computed(() => {
console.log('context.selectedKeys', context.selectedKeys);
return hasSide.value && getMenuFirstChildren(context.menuData, context.selectedKeys[0]);
});
// call menuHeaderRender
......@@ -140,12 +141,8 @@ const SiderMenu: FunctionalComponent<SiderMenuProps> = (props: SiderMenuProps) =
}}
class={`${baseClassName}-menu`}
{...{
'onUpdate:openKeys': ($event: string[]) => {
context?.setOpenKeys($event);
},
'onUpdate:selectedKeys': ($event: string[]) => {
context?.setSelectedKeys($event);
},
'onUpdate:openKeys': ($event: string[]) => onOpenKeys && onOpenKeys($event),
'onUpdate:selectedKeys': ($event: string[]) => onSelect && onSelect($event),
}}
/>
);
......
......@@ -141,6 +141,9 @@
.@{pro-layout-sider-menu-prefix-cls} {
&-logo {
padding: 16px 8px;
h1 {
display: none;
}
}
}
}
......
......@@ -52,6 +52,8 @@ export const TopNavHeader: FunctionalComponent<TopNavHeaderProps> = props => {
const {
prefixCls: propPrefixCls,
onMenuHeaderClick,
onOpenKeys,
onSelect,
contentWidth,
rightContentRender,
layout,
......@@ -89,12 +91,8 @@ export const TopNavHeader: FunctionalComponent<TopNavHeaderProps> = props => {
selectedKeys={context.selectedKeys}
class={{ 'top-nav-menu': props.mode === 'horizontal' }}
{...{
'onUpdate:openKeys': ($event: string[]) => {
context.setOpenKeys($event);
},
'onUpdate:selectedKeys': ($event: any) => {
context.setSelectedKeys($event);
},
'onUpdate:openKeys': ($event: string[]) => onOpenKeys && onOpenKeys($event),
'onUpdate:selectedKeys': ($event: string[]) => onSelect && onSelect($event),
}}
/>
</div>
......
......@@ -2205,6 +2205,11 @@
resolved "https://registry.yarnpkg.com/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.0.0-rc.2.tgz#7246341f666e7c6e65b13da420e2ce85714fbbca"
integrity sha512-1+7CwjQ0Kasml6rHoNQUmbISwqLNNfFVBUcZl6QBremUl296ZmLrVQPqJP5pyAAWjZke5bpI1hlj+LVVuT7Jcg==
"@vue/babel-helper-vue-transform-on@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.0.2.tgz#9b9c691cd06fc855221a2475c3cc831d774bc7dc"
integrity sha512-hz4R8tS5jMn8lDq6iD+yWL6XNB699pGIVLk7WSJnn1dbpjaazsjZQkieJoRX6gW5zpYSCFqQ7jUquPNY65tQYA==
"@vue/babel-plugin-jsx@^1.0.0-0":
version "1.0.0-rc.4"
resolved "https://registry.yarnpkg.com/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.0.0-rc.4.tgz#02c9ba2e01dc5251fd69a89afd49e9a1963331ba"
......@@ -2220,17 +2225,17 @@
html-tags "^3.1.0"
svg-tags "^1.0.0"
"@vue/babel-plugin-jsx@^1.0.0-rc.5":
version "1.0.0-rc.5"
resolved "https://registry.yarnpkg.com/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.0.0-rc.5.tgz#e440be2d0775ee3828cba2c38a03b19a92174865"
integrity sha512-IUxERGiEeX9i1Vt9UtBYqOtfPYjOwEP0sFyPRI8xjkXAhJpaAIwa8JdcYakOqzIlXwhk3XD+7VFdyr/v+rLLFw==
"@vue/babel-plugin-jsx@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.0.2.tgz#6bfd8e39c48e53391a56705649f81a35fe20b6a1"
integrity sha512-1uZlQCLCeuqJgDYLCmg3qfsvTVtOQiXh278ES4bvPTYYbv2Bi/rElLETK6AdjI9xxzyTUf5n1QEiH8Xxz0eZrg==
dependencies:
"@babel/helper-module-imports" "^7.0.0"
"@babel/plugin-syntax-jsx" "^7.0.0"
"@babel/template" "^7.0.0"
"@babel/traverse" "^7.0.0"
"@babel/types" "^7.0.0"
"@vue/babel-helper-vue-transform-on" "^1.0.0-rc.2"
"@vue/babel-helper-vue-transform-on" "^1.0.2"
camelcase "^6.0.0"
html-tags "^3.1.0"
svg-tags "^1.0.0"
......@@ -2484,6 +2489,17 @@
estree-walker "^2.0.1"
source-map "^0.6.1"
"@vue/compiler-core@3.0.5":
version "3.0.5"
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.0.5.tgz#a6e54cabe9536e74c6513acd2649f311af1d43ac"
integrity sha512-iFXwk2gmU/GGwN4hpBwDWWMLvpkIejf/AybcFtlQ5V1ur+5jwfBaV0Y1RXoR6ePfBPJixtKZ3PmN+M+HgMAtfQ==
dependencies:
"@babel/parser" "^7.12.0"
"@babel/types" "^7.12.0"
"@vue/shared" "3.0.5"
estree-walker "^2.0.1"
source-map "^0.6.1"
"@vue/compiler-dom@3.0.4":
version "3.0.4"
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.0.4.tgz#834fd4b15c5698cf9f4505c2bfbccca058a843eb"
......@@ -2492,6 +2508,14 @@
"@vue/compiler-core" "3.0.4"
"@vue/shared" "3.0.4"
"@vue/compiler-dom@3.0.5":
version "3.0.5"
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.0.5.tgz#7885a13e6d18f64dde8ebceec052ed2c102696c2"
integrity sha512-HSOSe2XSPuCkp20h4+HXSiPH9qkhz6YbW9z9ZtL5vef2T2PMugH7/osIFVSrRZP/Ul5twFZ7MIRlp8tPX6e4/g==
dependencies:
"@vue/compiler-core" "3.0.5"
"@vue/shared" "3.0.5"
"@vue/compiler-sfc@^3.0.3":
version "3.0.4"
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.0.4.tgz#2119fe1e68d2c268aafa20461c82c139a9adf8e0"
......@@ -2564,6 +2588,13 @@
dependencies:
"@vue/shared" "3.0.4"
"@vue/reactivity@3.0.5":
version "3.0.5"
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.0.5.tgz#e3789e4d523d845f9ae0b4d770e2b45594742fd2"
integrity sha512-3xodUE3sEIJgS7ntwUbopIpzzvi7vDAOjVamfb2l+v1FUg0jpd3gf62N2wggJw3fxBMr+QvyxpD+dBoxLsmAjw==
dependencies:
"@vue/shared" "3.0.5"
"@vue/runtime-core@3.0.4":
version "3.0.4"
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.0.4.tgz#a5b9a001560b1fd8c01a43f68b764c555de7836c"
......@@ -2572,6 +2603,14 @@
"@vue/reactivity" "3.0.4"
"@vue/shared" "3.0.4"
"@vue/runtime-core@3.0.5":
version "3.0.5"
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.0.5.tgz#da6331d5f300d5794e9e0ebdc8a8bd72a9e19962"
integrity sha512-Cnyi2NqREwOLcTEsIi1DQX1hHtkVj4eGm4hBG7HhokS05DqpK4/80jG6PCCnCH9rIJDB2FqtaODX397210plXg==
dependencies:
"@vue/reactivity" "3.0.5"
"@vue/shared" "3.0.5"
"@vue/runtime-dom@3.0.4":
version "3.0.4"
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.0.4.tgz#6f81aec545f24511d2c28a315aa3391420b69c68"
......@@ -2581,11 +2620,25 @@
"@vue/shared" "3.0.4"
csstype "^2.6.8"
"@vue/runtime-dom@3.0.5":
version "3.0.5"
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.0.5.tgz#1ce2c9c449e26ab06963da0064096e882a7a8935"
integrity sha512-iilX1KySeIzHHtErT6Y44db1rhWK5tAI0CiJIPr+SJoZ2jbjoOSE6ff/jfIQakchbm1d6jq6VtRVnp5xYdOXKA==
dependencies:
"@vue/runtime-core" "3.0.5"
"@vue/shared" "3.0.5"
csstype "^2.6.8"
"@vue/shared@3.0.4":
version "3.0.4"
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.0.4.tgz#6dc50f593bdfdeaa6183d1dbc15e2d45e7c6b8b3"
integrity sha512-Swfbz31AaMX48CpFl+YmIrqOH9MgJMTrltG9e26A4ZxYx9LjGuMV+41WnxFzS3Bc9nbrc6sDPM37G6nIT8NJSg==
"@vue/shared@3.0.5":
version "3.0.5"
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.0.5.tgz#c131d88bd6713cc4d93b3bb1372edb1983225ff0"
integrity sha512-gYsNoGkWejBxNO6SNRjOh/xKeZ0H0V+TFzaPzODfBjkAIb0aQgBuixC1brandC/CDJy1wYPwSoYrXpvul7m6yw==
"@vue/test-utils@^2.0.0-beta.2":
version "2.0.0-beta.12"
resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-2.0.0-beta.12.tgz#105a32f35c15cc43d470f88e0122f82bcfdf14ff"
......@@ -15829,7 +15882,7 @@ vue-types@^3.0.0, vue-types@^3.0.1:
dependencies:
is-plain-object "3.0.1"
vue@^3.0.0, vue@^3.0.0-0:
vue@^3.0.0:
version "3.0.4"
resolved "https://registry.yarnpkg.com/vue/-/vue-3.0.4.tgz#872c65c143f5717bd5387c61613d9f55f4cc0f43"
integrity sha512-2o+AiQF8sAupyhbyl3oxVCl3WCwC/n5NI7VMM+gVQ231qvSB8eI7sCBloloqDJK6yA367EEtmRSeSCf4sxCC+A==
......@@ -15838,6 +15891,15 @@ vue@^3.0.0, vue@^3.0.0-0:
"@vue/runtime-dom" "3.0.4"
"@vue/shared" "3.0.4"
vue@^3.0.5:
version "3.0.5"
resolved "https://registry.yarnpkg.com/vue/-/vue-3.0.5.tgz#de1b82eba24abfe71e0970fc9b8d4b2babdc3fe1"
integrity sha512-TfaprOmtsAfhQau7WsomXZ8d9op/dkQLNIq8qPV3A0Vxs6GR5E+c1rfJS1SDkXRQj+dFyfnec7+U0Be1huiScg==
dependencies:
"@vue/compiler-dom" "3.0.5"
"@vue/runtime-dom" "3.0.5"
"@vue/shared" "3.0.5"
w3c-hr-time@^1.0.1, w3c-hr-time@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment