Add API and UI to claim a member shelf
This commit is contained in:
parent
9ec850abfe
commit
9d6c2f8bb8
|
@ -1790,6 +1790,35 @@ class StorageSpaceViewSet(Base, List, Retrieve, Update):
|
||||||
queryset = models.StorageSpace.objects.all().order_by('id')
|
queryset = models.StorageSpace.objects.all().order_by('id')
|
||||||
serializer_class = serializers.StorageSpaceSerializer
|
serializer_class = serializers.StorageSpaceSerializer
|
||||||
|
|
||||||
|
@action(detail=False, methods=['post'], permission_classes=[AllowMetadata | IsAuthenticated])
|
||||||
|
def claim(self, request):
|
||||||
|
user = self.request.user
|
||||||
|
|
||||||
|
if user.storage.count():
|
||||||
|
raise exceptions.ValidationError(dict(shelf_id='You already have a shelf.'))
|
||||||
|
|
||||||
|
try:
|
||||||
|
shelf_id = str(request.data['shelf_id']).upper()
|
||||||
|
except KeyError:
|
||||||
|
raise exceptions.ValidationError(dict(shelf_id='This field is required.'))
|
||||||
|
|
||||||
|
try:
|
||||||
|
storage = models.StorageSpace.objects.get(shelf_id=shelf_id)
|
||||||
|
except models.StorageSpace.DoesNotExist:
|
||||||
|
raise exceptions.ValidationError(dict(shelf_id='Shelf ID not found.'))
|
||||||
|
|
||||||
|
if storage.location != 'member_shelves':
|
||||||
|
raise exceptions.ValidationError(dict(shelf_id='Not a member shelf. Please see a Director.'))
|
||||||
|
|
||||||
|
if storage.user:
|
||||||
|
owner = storage.user.member.preferred_name
|
||||||
|
raise exceptions.ValidationError(dict(shelf_id='Shelf already belongs to {}.'.format(owner)))
|
||||||
|
|
||||||
|
storage.user = user
|
||||||
|
storage.save()
|
||||||
|
|
||||||
|
return Response(200)
|
||||||
|
|
||||||
|
|
||||||
class RegistrationView(RegisterView):
|
class RegistrationView(RegisterView):
|
||||||
serializer_class = serializers.MyRegisterSerializer
|
serializer_class = serializers.MyRegisterSerializer
|
||||||
|
|
|
@ -27,7 +27,7 @@ import { Subscribe } from './PayPal.js';
|
||||||
import { PasswordReset, ConfirmReset } from './PasswordReset.js';
|
import { PasswordReset, ConfirmReset } from './PasswordReset.js';
|
||||||
import { NotFound, PleaseLogin } from './Misc.js';
|
import { NotFound, PleaseLogin } from './Misc.js';
|
||||||
import { Debug } from './Debug.js';
|
import { Debug } from './Debug.js';
|
||||||
import { StorageDetail } from './Storage.js';
|
import { StorageDetail, ClaimShelf } from './Storage.js';
|
||||||
import { Garden } from './Garden.js';
|
import { Garden } from './Garden.js';
|
||||||
import { Footer } from './Footer.js';
|
import { Footer } from './Footer.js';
|
||||||
import { LCARS1Display, LCARS2Display } from './Display.js';
|
import { LCARS1Display, LCARS2Display } from './Display.js';
|
||||||
|
@ -285,6 +285,10 @@ function App() {
|
||||||
|
|
||||||
{user && user.member.set_details ?
|
{user && user.member.set_details ?
|
||||||
<Switch>
|
<Switch>
|
||||||
|
<Route path='/claimshelf'>
|
||||||
|
<ClaimShelf token={token} user={user} refreshUser={refreshUser} />
|
||||||
|
</Route>
|
||||||
|
|
||||||
<Route path='/account'>
|
<Route path='/account'>
|
||||||
<Account token={token} user={user} refreshUser={refreshUser} />
|
<Account token={token} user={user} refreshUser={refreshUser} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
|
@ -77,7 +77,7 @@ function MemberInfo(props) {
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
'None'
|
<>None <Link to='/claimshelf'>[claim]</Link></>
|
||||||
}
|
}
|
||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
|
|
|
@ -241,3 +241,82 @@ export function StorageList(props) {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function ClaimShelfForm(props) {
|
||||||
|
const { token, user, refreshUser } = props;
|
||||||
|
const member = user.member;
|
||||||
|
const [input, setInput] = useState({});
|
||||||
|
const [error, setError] = useState({});
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
|
const handleValues = (e, v) => setInput({ ...input, [v.name]: v.value });
|
||||||
|
const handleChange = (e) => handleValues(e, e.currentTarget);
|
||||||
|
|
||||||
|
const handleSubmit = (e) => {
|
||||||
|
if (loading) return;
|
||||||
|
setLoading(true);
|
||||||
|
requester('/storage/claim/', 'POST', token, input)
|
||||||
|
.then(res => {
|
||||||
|
setError({});
|
||||||
|
refreshUser();
|
||||||
|
history.push('/');
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
setLoading(false);
|
||||||
|
console.log(err);
|
||||||
|
setError(err.data);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const makeProps = (name) => ({
|
||||||
|
name: name,
|
||||||
|
onChange: handleChange,
|
||||||
|
value: input[name] || '',
|
||||||
|
error: error[name],
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Form onSubmit={handleSubmit}>
|
||||||
|
<div className='field'>
|
||||||
|
<label>Spaceport Username</label>
|
||||||
|
<p>{user.username}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Form.Input
|
||||||
|
label='Shelf ID'
|
||||||
|
autoComplete='off'
|
||||||
|
required
|
||||||
|
{...makeProps('shelf_id')}
|
||||||
|
maxLength={3}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Form.Button loading={loading} error={error.non_field_errors || error.detail}>
|
||||||
|
Submit
|
||||||
|
</Form.Button>
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export function ClaimShelf(props) {
|
||||||
|
const { token, user } = props;
|
||||||
|
const [error, setError] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<Grid stackable columns={2}>
|
||||||
|
<Grid.Column>
|
||||||
|
<Header size='large'>Claim Member Shelf</Header>
|
||||||
|
|
||||||
|
<p>Use this form to claim a member shelf.</p>
|
||||||
|
|
||||||
|
<p>Please make sure your name and contact info are visible on the shelf.</p>
|
||||||
|
|
||||||
|
<p>Use the Shelf ID visible on the corner label (A1A, A2B, etc.)</p>
|
||||||
|
|
||||||
|
<ClaimShelfForm {...props} />
|
||||||
|
</Grid.Column>
|
||||||
|
</Grid>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user